From 27d736c6be8876ea3295649f74d504a6ad9b76bf Mon Sep 17 00:00:00 2001 From: Eugene Kulabuhov Date: Wed, 27 May 2020 17:22:15 +0800 Subject: [PATCH 1/3] 2655 Function calls via delve 'call' are not supported --- src/debugAdapter/goDebug.ts | 69 ++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts index 09075bad7b..fd4357484c 100644 --- a/src/debugAdapter/goDebug.ts +++ b/src/debugAdapter/goDebug.ts @@ -149,6 +149,7 @@ interface DebugThread { pc: number; goroutineID: number; function?: DebugFunction; + ReturnValues: DebugVariable[]; } interface StacktraceOut { @@ -1572,21 +1573,63 @@ export class GoDebugSession extends LoggingDebugSession { protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void { log('EvaluateRequest'); - this.evaluateRequestImpl(args).then( - (out) => { - const variable = this.delve.isApiV1 ? out : (out).Variable; - // #2326: Set the fully qualified name for variable mapping - variable.fullyQualifiedName = variable.name; - response.body = this.convertDebugVariableToProtocolVariable(variable); + const re = new RegExp(/\w+(?=\(.*\))/, 'g'); + if (re.test(args.expression)) { + this.evaluateCallImpl(args).then(out => { + const state = this.delve.isApiV1 ? out : (out).State; + response.body = this.convertDebugVariableToProtocolVariable(state.currentThread.ReturnValues[0]); this.sendResponse(response); - log('EvaluateResponse'); - }, - (err) => { - this.sendErrorResponse(response, 2009, 'Unable to eval expression: "{e}"', { - e: err.toString() + log('EvaluateCallResponse'); + }, err => { + this.sendErrorResponse(response, 2009, 'Unable to complete call: "{e}"', { e: err.toString() }); + }); + } else { + this.evaluateRequestImpl(args).then( + (out) => { + const variable = this.delve.isApiV1 ? out : (out).Variable; + // #2326: Set the fully qualified name for variable mapping + variable.fullyQualifiedName = variable.name; + response.body = this.convertDebugVariableToProtocolVariable(variable); + this.sendResponse(response); + log('EvaluateResponse'); + }, + (err) => { + this.sendErrorResponse(response, 2009, 'Unable to eval expression: "{e}"', { + e: err.toString() + }); + } + ); + } + } + + private evaluateCallImpl(args: DebugProtocol.EvaluateArguments): Thenable { + // default to the topmost stack frame of the current goroutine + let goroutineId = -1; + let frameId = 0; + // args.frameId won't be specified when evaluating global vars + if (args.frameId) { + [goroutineId, frameId] = this.stackFrameHandles.get(args.frameId); + } + const scope = { + goroutineID: goroutineId, + frame: frameId + }; + const evalSymbolArgs = this.delve.isApiV1 ? { + symbol: args.expression, + scope + } : { + Expr: args.expression, + Scope: scope, + Cfg: this.delve.loadConfig, + Unsafe: true + }; + const returnValue = this.delve.callPromise('Command', + [{ name: 'call', returnInfoLoadConfig: this.delve.loadConfig, expr: evalSymbolArgs.Expr, unsafe: false, goroutineID: scope.goroutineID }]).then(val => val, + err => { + logError('Failed to call function: ', JSON.stringify(evalSymbolArgs.Expr, null, ' '), '\n\rCall error:', err.toString()); + return Promise.reject(err); }); - } - ); + return returnValue; } protected setVariableRequest( From 49b29047d19373a5f0c8e1e41ffba0a7f64cf21b Mon Sep 17 00:00:00 2001 From: Eugene Kulabuhov Date: Sun, 28 Jun 2020 10:59:13 +0800 Subject: [PATCH 2/3] Formatted according to eslint rules --- src/debugAdapter/goDebug.ts | 82 ++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts index fd4357484c..9ac5a39a7b 100644 --- a/src/debugAdapter/goDebug.ts +++ b/src/debugAdapter/goDebug.ts @@ -1575,12 +1575,12 @@ export class GoDebugSession extends LoggingDebugSession { log('EvaluateRequest'); const re = new RegExp(/\w+(?=\(.*\))/, 'g'); if (re.test(args.expression)) { - this.evaluateCallImpl(args).then(out => { + this.evaluateCallImpl(args).then((out) => { const state = this.delve.isApiV1 ? out : (out).State; response.body = this.convertDebugVariableToProtocolVariable(state.currentThread.ReturnValues[0]); this.sendResponse(response); log('EvaluateCallResponse'); - }, err => { + }, (err) => { this.sendErrorResponse(response, 2009, 'Unable to complete call: "{e}"', { e: err.toString() }); }); } else { @@ -1602,36 +1602,6 @@ export class GoDebugSession extends LoggingDebugSession { } } - private evaluateCallImpl(args: DebugProtocol.EvaluateArguments): Thenable { - // default to the topmost stack frame of the current goroutine - let goroutineId = -1; - let frameId = 0; - // args.frameId won't be specified when evaluating global vars - if (args.frameId) { - [goroutineId, frameId] = this.stackFrameHandles.get(args.frameId); - } - const scope = { - goroutineID: goroutineId, - frame: frameId - }; - const evalSymbolArgs = this.delve.isApiV1 ? { - symbol: args.expression, - scope - } : { - Expr: args.expression, - Scope: scope, - Cfg: this.delve.loadConfig, - Unsafe: true - }; - const returnValue = this.delve.callPromise('Command', - [{ name: 'call', returnInfoLoadConfig: this.delve.loadConfig, expr: evalSymbolArgs.Expr, unsafe: false, goroutineID: scope.goroutineID }]).then(val => val, - err => { - logError('Failed to call function: ', JSON.stringify(evalSymbolArgs.Expr, null, ' '), '\n\rCall error:', err.toString()); - return Promise.reject(err); - }); - return returnValue; - } - protected setVariableRequest( response: DebugProtocol.SetVariableResponse, args: DebugProtocol.SetVariableArguments @@ -2099,6 +2069,54 @@ export class GoDebugSession extends LoggingDebugSession { return this.delve.callPromise('Command', [{ name: 'continue' }]).then(callback, errorCallback); } + private evaluateCallImpl(args: DebugProtocol.EvaluateArguments): Thenable { + // default to the topmost stack frame of the current goroutine + let goroutineId = -1; + let frameId = 0; + // args.frameId won't be specified when evaluating global vars + if (args.frameId) { + [goroutineId, frameId] = this.stackFrameHandles.get(args.frameId); + } + const scope = { + goroutineID: goroutineId, + frame: frameId + }; + const evalSymbolArgs = this.delve.isApiV1 + ? { + symbol: args.expression, + scope + } + : { + Expr: args.expression, + Scope: scope, + Cfg: this.delve.loadConfig, + Unsafe: true + }; + const returnValue = this.delve + .callPromise('Command', [ + { + name: 'call', + returnInfoLoadConfig: this.delve.loadConfig, + expr: evalSymbolArgs.Expr, + unsafe: false, + goroutineID: scope.goroutineID + } + ]) + .then( + (val) => val, + (err) => { + logError( + 'Failed to call function: ', + JSON.stringify(evalSymbolArgs.Expr, null, ' '), + '\n\rCall error:', + err.toString() + ); + return Promise.reject(err); + } + ); + return returnValue; + } + private evaluateRequestImpl(args: DebugProtocol.EvaluateArguments): Thenable { // default to the topmost stack frame of the current goroutine let goroutineId = -1; From c321337eab0805302e8e30d321f94c5f8363cfa6 Mon Sep 17 00:00:00 2001 From: Eugene Kulabuhov Date: Sun, 28 Jun 2020 11:17:28 +0800 Subject: [PATCH 3/3] Removed extra spaces --- src/debugAdapter/goDebug.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts index a96cda199b..d152e544b1 100644 --- a/src/debugAdapter/goDebug.ts +++ b/src/debugAdapter/goDebug.ts @@ -2135,15 +2135,15 @@ export class GoDebugSession extends LoggingDebugSession { }; const evalSymbolArgs = this.delve.isApiV1 ? { - symbol: args.expression, - scope - } + symbol: args.expression, + scope + } : { - Expr: args.expression, - Scope: scope, - Cfg: this.delve.loadConfig, - Unsafe: true - }; + Expr: args.expression, + Scope: scope, + Cfg: this.delve.loadConfig, + Unsafe: true + }; const returnValue = this.delve .callPromise('Command', [ {