From de8abc62bcf8ab4d031b60dd1e45ec1d5fc90884 Mon Sep 17 00:00:00 2001 From: Dave Holoway Date: Sun, 11 Nov 2018 17:57:32 +0000 Subject: [PATCH] add trace support (#38) * add basic support for sending console logs to OutputWindow * add trace config setting * standardise logs --- package.json | 5 +++++ src/debugMain.js | 21 ++++++++++++++++++--- src/jdwp.js | 6 +++--- src/jq-promise.js | 2 +- src/util.js | 11 ++++++++--- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 7eb5f37..f9295d7 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,11 @@ "type": "string", "description": "Target Device ID (as indicated by 'adb devices'). Use this to specify which device is used for deployment when multiple devices are connected.", "default": "" + }, + "trace": { + "type": "boolean", + "description": "Set to true to output debugging logs for diagnostics", + "default": "false" } } } diff --git a/src/debugMain.js b/src/debugMain.js index 77f51d9..63be531 100644 --- a/src/debugMain.js +++ b/src/debugMain.js @@ -17,7 +17,7 @@ const { ADBClient } = require('./adbclient'); const { Debugger } = require('./debugger'); const $ = require('./jq-promise'); const { AndroidThread } = require('./threads'); -const { D, isEmptyObject } = require('./util'); +const { D, onMessagePrint, isEmptyObject } = require('./util'); const { AndroidVariables } = require('./variables'); const { evaluate } = require('./expressions'); const ws_proxy = require('./wsproxy').proxy.Server(6037, 5037); @@ -73,6 +73,9 @@ class AndroidDebugSession extends DebugSession { // flag to distinguish unexpected disconnection events (initiated from the device) vs user-terminated requests this._isDisconnecting = false; + // trace flag for printing diagnostic messages to the client Output Window + this.trace = false; + // this debugger uses one-based lines and columns this.setDebuggerLinesStartAt1(true); this.setDebuggerColumnsStartAt1(true); @@ -106,14 +109,19 @@ class AndroidDebugSession extends DebugSession { } LOG(msg) { - D(msg); + if (!this.trace) { + D(msg); + } // VSCode no longer auto-newlines output this.sendEvent(new OutputEvent(msg + os.EOL)); } WARN(msg) { D(msg = 'Warning: '+msg); - this.sendEvent(new OutputEvent(msg + os.EOL)); + // the message will already be sent if trace is enabled + if (!this.trace) { + this.sendEvent(new OutputEvent(msg + os.EOL)); + } } failRequest(msg, response) { @@ -223,6 +231,10 @@ class AndroidDebugSession extends DebugSession { } launchRequest(response/*: DebugProtocol.LaunchResponse*/, args/*: LaunchRequestArguments*/) { + if (args && args.trace) { + this.trace = args.trace; + onMessagePrint(this.LOG.bind(this)); + } try { D('Launching: ' + JSON.stringify(args)); } catch(ex) {} // app_src_root must end in a path-separator for correct validation of sub-paths @@ -360,6 +372,9 @@ class AndroidDebugSession extends DebugSession { this.sendResponse(response); return this.dbgr.resume(); }) + .then(() => { + this.LOG('Application started'); + }) .fail(e => { // exceptions use message, adbclient uses msg this.LOG('Launch failed: '+(e.message||e.msg||'No additional information is available')); diff --git a/src/jdwp.js b/src/jdwp.js index d9cb0dd..87aa4e8 100644 --- a/src/jdwp.js +++ b/src/jdwp.js @@ -1,5 +1,5 @@ const $ = require('./jq-promise'); -const { atob,btoa,D,getutf8bytes,fromutf8bytes,intToHex } = require('./util'); +const { btoa,D,E,getutf8bytes,fromutf8bytes,intToHex } = require('./util'); /* JDWP - The Java Debug Wire Protocol */ @@ -96,8 +96,8 @@ function _JDWP() { return; } - if (this.errorcode != 0) { - console.error("Command failed: error " + this.errorcode, this); + if (this.errorcode !== 0) { + E(`JDWP command failed '${this.command.name}'. Error ${this.errorcode}`, this); } if (!this.errorcode && this.command && this.command.replydecodefn) { diff --git a/src/jq-promise.js b/src/jq-promise.js index e1545f6..ce40665 100644 --- a/src/jq-promise.js +++ b/src/jq-promise.js @@ -40,7 +40,7 @@ var Deferred = exports.Deferred = function(p, parent) { var faildef = $.Deferred(null, this); var p = this._promise.catch(function(a) { if (a.stack) { - console.error(a.stack); + util.E(a.stack); a = [a]; } if (this.def._context === null && this.def._parent) diff --git a/src/util.js b/src/util.js index 35a89c5..e98f489 100644 --- a/src/util.js +++ b/src/util.js @@ -1,13 +1,18 @@ const crypto = require('crypto'); var nofn = function () { }; -var D = exports.D = console.log.bind(console); -var E = exports.E = console.error.bind(console); -var W = exports.W = console.warn.bind(console); +const messagePrintCallbacks = new Set(); +var D = exports.D = (...args) => (console.log(...args), messagePrintCallbacks.forEach(cb => cb(...args))) +var E = exports.E = (...args) => (console.error(...args), messagePrintCallbacks.forEach(cb => cb(...args))) +var W = exports.W = (...args) => (console.warn(...args), messagePrintCallbacks.forEach(cb => cb(...args))) var DD = nofn, cl = D, printf = D; var print_jdwp_data = nofn;// _print_jdwp_data; var print_packet = nofn;//_print_packet; +exports.onMessagePrint = function(cb) { + messagePrintCallbacks.add(cb); +} + Array.first = function (arr, fn, defaultvalue) { var idx = Array.indexOfFirst(arr, fn); return idx < 0 ? defaultvalue : arr[idx];