diff --git a/src/GDBDebugSession.ts b/src/GDBDebugSession.ts index a71ae352..2f888368 100644 --- a/src/GDBDebugSession.ts +++ b/src/GDBDebugSession.ts @@ -443,71 +443,62 @@ export class GDBDebugSession extends LoggingDebugSession { args: DebugProtocol.EvaluateArguments): Promise { response.body = { result: 'Error: could not evaluate expression', variablesReference: 0 }; // default response try { - switch (args.context) { - case 'repl': - response.body = { result: 'placeholder text', variablesReference: 0 }; - await this.gdb.sendCommand(args.expression); + if (args.frameId) { + const frame = this.frameHandles.get(args.frameId); + if (!frame) { this.sendResponse(response); - break; - case 'watch': { - if (args.frameId) { - const frame = this.frameHandles.get(args.frameId); - if (!frame) { - this.sendResponse(response); - return; - } - try { - const stackDepth = await mi.sendStackInfoDepth(this.gdb, { maxDepth: 100 }); - const depth = parseInt(stackDepth.depth, 10); - let varobj = varMgr.getVar(frame.frameId, frame.threadId, depth, args.expression); - if (!varobj) { + return; + } + try { + const stackDepth = await mi.sendStackInfoDepth(this.gdb, { maxDepth: 100 }); + const depth = parseInt(stackDepth.depth, 10); + let varobj = varMgr.getVar(frame.frameId, frame.threadId, depth, args.expression); + if (!varobj) { + const varCreateResponse = await mi.sendVarCreate(this.gdb, + { expression: args.expression, frame: 'current' }); + varobj = varMgr.addVar(frame.frameId, frame.threadId, depth, args.expression, false, + false, varCreateResponse); + } else { + const vup = await mi.sendVarUpdate(this.gdb, { + threadId: frame.threadId, + name: varobj.varname, + }); + const update = vup.changelist[0]; + if (update) { + if (update.in_scope === 'true') { + if (update.name === varobj.varname) { + varobj.value = update.value; + } + } else { + varMgr.removeVar(this.gdb, frame.frameId, frame.threadId, depth, + varobj.varname); + await mi.sendVarDelete(this.gdb, { varname: varobj.varname }); const varCreateResponse = await mi.sendVarCreate(this.gdb, { expression: args.expression, frame: 'current' }); - varobj = varMgr.addVar(frame.frameId, frame.threadId, depth, args.expression, false, - false, varCreateResponse); - } else { - const vup = await mi.sendVarUpdate(this.gdb, { - threadId: frame.threadId, - name: varobj.varname, - }); - const update = vup.changelist[0]; - if (update) { - if (update.in_scope === 'true') { - if (update.name === varobj.varname) { - varobj.value = update.value; - } - } else { - varMgr.removeVar(this.gdb, frame.frameId, frame.threadId, depth, - varobj.varname); - await mi.sendVarDelete(this.gdb, { varname: varobj.varname }); - const varCreateResponse = await mi.sendVarCreate(this.gdb, - { expression: args.expression, frame: 'current' }); - varobj = varMgr.addVar(frame.frameId, frame.threadId, depth, args.expression, - false, false, varCreateResponse); - } - } - } - if (varobj) { - response.body = { - result: varobj.value, - type: varobj.type, - variablesReference: parseInt(varobj.numchild, 10) > 0 - ? this.variableHandles.create({ - type: 'object', - frameHandle: args.frameId, - varobjName: varobj.varname, - }) - : 0, - }; + varobj = varMgr.addVar(frame.frameId, frame.threadId, depth, args.expression, + false, false, varCreateResponse); } - } catch (err) { - // if any of the gdb calls fail, just report we can't complete the evaluation } } - this.sendResponse(response); - break; + if (varobj) { + response.body = { + result: varobj.value, + type: varobj.type, + variablesReference: parseInt(varobj.numchild, 10) > 0 + ? this.variableHandles.create({ + type: 'object', + frameHandle: args.frameId, + varobjName: varobj.varname, + }) + : 0, + }; + } + } catch (err) { + // if any of the gdb calls fail, just report we can't complete the evaluation } } + + this.sendResponse(response); } catch (err) { this.sendErrorResponse(response, 1, err.message); } diff --git a/src/integration-tests/evaluate.spec.ts b/src/integration-tests/evaluate.spec.ts new file mode 100644 index 00000000..d2e44e44 --- /dev/null +++ b/src/integration-tests/evaluate.spec.ts @@ -0,0 +1,60 @@ +/********************************************************************* + * Copyright (c) 2019 Ericsson and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *********************************************************************/ + +import { expect } from 'chai'; +import * as path from 'path'; +import { DebugClient } from 'vscode-debugadapter-testsupport/lib/debugClient'; +import { getScopes, Scope, standardBefore, standardBeforeEach, testProgramsDir } from './utils'; + +// Allow non-arrow functions: https://mochajs.org/#arrow-functions +// tslint:disable:only-arrow-functions + +let dc: DebugClient; +let scope: Scope; + +const evaluateProgram = path.join(testProgramsDir, 'evaluate'); +const evaluateSrc = path.join(testProgramsDir, 'evaluate.cpp'); + +before(standardBefore); + +beforeEach(async function() { + // Move the timeout out of the way if the adapter is going to be debugged. + if (process.env.INSPECT_DEBUG_ADAPTER) { + this.timeout(9999999); + } + dc = await standardBeforeEach(); + await dc.hitBreakpoint({ + verbose: true, + program: evaluateProgram, + logFile: '/tmp/gdb.log', + }, { path: evaluateSrc, line: 2 }); + scope = await getScopes(dc); +}); + +afterEach(async function() { + await dc.stop(); +}); + +describe('evaluate request', function() { + // Move the timeout out of the way if the adapter is going to be debugged. + if (process.env.INSPECT_DEBUG_ADAPTER) { + this.timeout(9999999); + } + + it('should evaluate a simple literal expression', async function() { + const res = await dc.evaluateRequest({ + context: 'repl', + expression: '2', + frameId: scope.frameId, + }); + + expect(res.body.result).eq('2'); + }); +}); diff --git a/src/integration-tests/test-programs/.gitignore b/src/integration-tests/test-programs/.gitignore index 3193bac1..a61fc1dd 100644 --- a/src/integration-tests/test-programs/.gitignore +++ b/src/integration-tests/test-programs/.gitignore @@ -1,4 +1,5 @@ empty +evaluate mem vars *.o diff --git a/src/integration-tests/test-programs/Makefile b/src/integration-tests/test-programs/Makefile index 9fbe8fb4..86532055 100644 --- a/src/integration-tests/test-programs/Makefile +++ b/src/integration-tests/test-programs/Makefile @@ -1,4 +1,4 @@ -BINS = empty vars vars_cpp mem +BINS = empty evaluate vars vars_cpp mem .PHONY: all all: $(BINS) @@ -11,6 +11,9 @@ LINK_CXX = $(CXX) -o $@ $^ empty: empty.o $(LINK) +evaluate: evaluate.o + $(LINK) + mem: mem.o $(LINK) diff --git a/src/integration-tests/test-programs/evaluate.cpp b/src/integration-tests/test-programs/evaluate.cpp new file mode 100644 index 00000000..33c14ce1 --- /dev/null +++ b/src/integration-tests/test-programs/evaluate.cpp @@ -0,0 +1,3 @@ +int main() { + return 0; +}