mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 01:48:18 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1e7c86092 | ||
|
|
690f9dc23a | ||
|
|
27ecd41b68 | ||
|
|
756a1cea29 | ||
|
|
fc2ce97a23 | ||
|
|
de8abc62bc | ||
|
|
8cc31476b3 |
@@ -1,5 +1,12 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
### version 0.6.0
|
||||||
|
* Fix issue with breakpoints not enabling correctly
|
||||||
|
* Fix issue with JDWP failure on breakpoint hit
|
||||||
|
* Added support for diagnostic logs using trace configuration option
|
||||||
|
* Updated default apkFile path to match current releases of Android Studio
|
||||||
|
* Updated package dependencies
|
||||||
|
|
||||||
### version 0.5.0
|
### version 0.5.0
|
||||||
* Debugger support for Kotlin source files
|
* Debugger support for Kotlin source files
|
||||||
* Exception UI
|
* Exception UI
|
||||||
|
|||||||
3091
package-lock.json
generated
Normal file
3091
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "android-dev-ext",
|
"name": "android-dev-ext",
|
||||||
"displayName": "Android",
|
"displayName": "Android",
|
||||||
"description": "Android debugging support for VS Code",
|
"description": "Android debugging support for VS Code",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"publisher": "adelphes",
|
"publisher": "adelphes",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"debuggers": [
|
"debuggers": [
|
||||||
{
|
{
|
||||||
"type": "android",
|
"type": "android",
|
||||||
"label": "Android Debug",
|
"label": "Android",
|
||||||
"program": "./src/debugMain.js",
|
"program": "./src/debugMain.js",
|
||||||
"runtime": "node",
|
"runtime": "node",
|
||||||
"configurationAttributes": {
|
"configurationAttributes": {
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
"apkFile": {
|
"apkFile": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Fully qualified path to the built APK (Android Application Package)",
|
"description": "Fully qualified path to the built APK (Android Application Package)",
|
||||||
"default": "${workspaceRoot}/app/build/outputs/apk/app-debug.apk"
|
"default": "${workspaceRoot}/app/build/outputs/apk/debug/app-debug.apk"
|
||||||
},
|
},
|
||||||
"adbPort": {
|
"adbPort": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@@ -93,6 +93,11 @@
|
|||||||
"type": "string",
|
"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.",
|
"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": ""
|
"default": ""
|
||||||
|
},
|
||||||
|
"trace": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Set to true to output debugging logs for diagnostics",
|
||||||
|
"default": "false"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,10 +105,10 @@
|
|||||||
"initialConfigurations": [
|
"initialConfigurations": [
|
||||||
{
|
{
|
||||||
"type": "android",
|
"type": "android",
|
||||||
"name": "Android Debug",
|
"name": "Android",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"appSrcRoot": "${workspaceRoot}/app/src/main",
|
"appSrcRoot": "${workspaceRoot}/app/src/main",
|
||||||
"apkFile": "${workspaceRoot}/app/build/outputs/apk/app-debug.apk",
|
"apkFile": "${workspaceRoot}/app/build/outputs/apk/debug/app-debug.apk",
|
||||||
"adbPort": 5037
|
"adbPort": 5037
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -116,7 +121,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "${2:Launch App}",
|
"name": "${2:Launch App}",
|
||||||
"appSrcRoot": "^\"\\${workspaceRoot}/app/src/main\"",
|
"appSrcRoot": "^\"\\${workspaceRoot}/app/src/main\"",
|
||||||
"apkFile": "^\"\\${workspaceRoot}/app/build/outputs/apk/app-debug.apk\"",
|
"apkFile": "^\"\\${workspaceRoot}/app/build/outputs/apk/debug/app-debug.apk\"",
|
||||||
"adbPort": 5037
|
"adbPort": 5037
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,19 +135,19 @@
|
|||||||
"test": "node ./node_modules/vscode/bin/test"
|
"test": "node ./node_modules/vscode/bin/test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vscode-debugprotocol": "^1.20.0",
|
"vscode-debugprotocol": "^1.32.0",
|
||||||
"vscode-debugadapter": "^1.20.0",
|
"vscode-debugadapter": "^1.32.0",
|
||||||
"long": "^3.2.0",
|
"long": "^4.0.0",
|
||||||
"ws": "^1.1.1",
|
"ws": "^1.1.1",
|
||||||
"xmldom": "^0.1.27",
|
"xmldom": "^0.1.27",
|
||||||
"xpath": "^0.0.23"
|
"xpath": "^0.0.27"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^2.0.3",
|
"typescript": "^3.1.6",
|
||||||
"vscode": "^1.0.0",
|
"vscode": "^1.1.21",
|
||||||
"mocha": "^2.3.3",
|
"mocha": "^5.2.0",
|
||||||
"eslint": "^3.6.0",
|
"eslint": "^5.9.0",
|
||||||
"@types/node": "^6.0.40",
|
"@types/node": "^10.12.5",
|
||||||
"@types/mocha": "^2.2.32"
|
"@types/mocha": "^5.2.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const { ADBClient } = require('./adbclient');
|
|||||||
const { Debugger } = require('./debugger');
|
const { Debugger } = require('./debugger');
|
||||||
const $ = require('./jq-promise');
|
const $ = require('./jq-promise');
|
||||||
const { AndroidThread } = require('./threads');
|
const { AndroidThread } = require('./threads');
|
||||||
const { D, isEmptyObject } = require('./util');
|
const { D, onMessagePrint, isEmptyObject } = require('./util');
|
||||||
const { AndroidVariables } = require('./variables');
|
const { AndroidVariables } = require('./variables');
|
||||||
const { evaluate } = require('./expressions');
|
const { evaluate } = require('./expressions');
|
||||||
const ws_proxy = require('./wsproxy').proxy.Server(6037, 5037);
|
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
|
// flag to distinguish unexpected disconnection events (initiated from the device) vs user-terminated requests
|
||||||
this._isDisconnecting = false;
|
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 debugger uses one-based lines and columns
|
||||||
this.setDebuggerLinesStartAt1(true);
|
this.setDebuggerLinesStartAt1(true);
|
||||||
this.setDebuggerColumnsStartAt1(true);
|
this.setDebuggerColumnsStartAt1(true);
|
||||||
@@ -106,14 +109,19 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG(msg) {
|
LOG(msg) {
|
||||||
D(msg);
|
if (!this.trace) {
|
||||||
|
D(msg);
|
||||||
|
}
|
||||||
// VSCode no longer auto-newlines output
|
// VSCode no longer auto-newlines output
|
||||||
this.sendEvent(new OutputEvent(msg + os.EOL));
|
this.sendEvent(new OutputEvent(msg + os.EOL));
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN(msg) {
|
WARN(msg) {
|
||||||
D(msg = 'Warning: '+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) {
|
failRequest(msg, response) {
|
||||||
@@ -223,6 +231,10 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
launchRequest(response/*: DebugProtocol.LaunchResponse*/, args/*: LaunchRequestArguments*/) {
|
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) {}
|
try { D('Launching: ' + JSON.stringify(args)); } catch(ex) {}
|
||||||
// app_src_root must end in a path-separator for correct validation of sub-paths
|
// 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);
|
this.sendResponse(response);
|
||||||
return this.dbgr.resume();
|
return this.dbgr.resume();
|
||||||
})
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.LOG('Application started');
|
||||||
|
})
|
||||||
.fail(e => {
|
.fail(e => {
|
||||||
// exceptions use message, adbclient uses msg
|
// exceptions use message, adbclient uses msg
|
||||||
this.LOG('Launch failed: '+(e.message||e.msg||'No additional information is available'));
|
this.LOG('Launch failed: '+(e.message||e.msg||'No additional information is available'));
|
||||||
@@ -521,6 +536,7 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configurationDoneRequest(response/*, args*/) {
|
configurationDoneRequest(response/*, args*/) {
|
||||||
|
D('configurationDoneRequest');
|
||||||
this.waitForConfigurationDone.resolve();
|
this.waitForConfigurationDone.resolve();
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
}
|
}
|
||||||
@@ -551,13 +567,14 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onBreakpointStateChange(e) {
|
onBreakpointStateChange(e) {
|
||||||
|
D('onBreakpointStateChange');
|
||||||
e.breakpoints.forEach(javabp => {
|
e.breakpoints.forEach(javabp => {
|
||||||
// if there's no associated vsbp we're deleting it, so just ignore the update
|
// if there's no associated vsbp we're deleting it, so just ignore the update
|
||||||
if (!javabp.vsbp) return;
|
if (!javabp.vsbp) return;
|
||||||
var verified = !!javabp.state.match(/set|enabled/);
|
var verified = !!javabp.state.match(/set|enabled/);
|
||||||
javabp.vsbp.verified = verified;
|
javabp.vsbp.verified = verified;
|
||||||
javabp.vsbp.message = null;
|
javabp.vsbp.message = null;
|
||||||
this.sendEvent(new BreakpointEvent('updated', javabp.vsbp));
|
this.sendEvent(new BreakpointEvent('changed', javabp.vsbp));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,6 +599,14 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sendBPResponse = (response, breakpoints) => {
|
||||||
|
D('setBreakPointsRequest response ' + JSON.stringify(breakpoints.map(bp => bp.verified)));
|
||||||
|
response.body = {
|
||||||
|
breakpoints,
|
||||||
|
};
|
||||||
|
this.sendResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
// the file must lie inside one of the source packages we found (and it must be have a .java extension)
|
// the file must lie inside one of the source packages we found (and it must be have a .java extension)
|
||||||
var srcfolder = path.dirname(srcfpn);
|
var srcfolder = path.dirname(srcfpn);
|
||||||
var pkginfo;
|
var pkginfo;
|
||||||
@@ -597,10 +622,7 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
if (!pkginfo || !/\.(java|kt)$/i.test(srcfpn)) {
|
if (!pkginfo || !/\.(java|kt)$/i.test(srcfpn)) {
|
||||||
// source file is not a java file or is outside of the known source packages
|
// source file is not a java file or is outside of the known source packages
|
||||||
// just send back a list of unverified breakpoints
|
// just send back a list of unverified breakpoints
|
||||||
response.body = {
|
sendBPResponse(response, args.breakpoints.map(bp => unverified_breakpoint(bp, 'The breakpoint location is not valid')));
|
||||||
breakpoints: args.breakpoints.map(bp => unverified_breakpoint(bp, 'The breakpoint location is not valid'))
|
|
||||||
};
|
|
||||||
this.sendResponse(response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,10 +689,7 @@ class AndroidDebugSession extends DebugSession {
|
|||||||
this._setup_breakpoints(this._queue[0]).then(javabp_arr => {
|
this._setup_breakpoints(this._queue[0]).then(javabp_arr => {
|
||||||
// send back the VS Breakpoint instances
|
// send back the VS Breakpoint instances
|
||||||
var response = this._queue[0].response;
|
var response = this._queue[0].response;
|
||||||
response.body = {
|
sendBPResponse(response, javabp_arr.map(javabp => javabp.vsbp));
|
||||||
breakpoints: javabp_arr.map(javabp => javabp.vsbp)
|
|
||||||
};
|
|
||||||
this._dbgr.sendResponse(response);
|
|
||||||
// .. and do the next one
|
// .. and do the next one
|
||||||
this._queue.shift();
|
this._queue.shift();
|
||||||
this._next();
|
this._next();
|
||||||
|
|||||||
@@ -1425,6 +1425,15 @@ Debugger.prototype = {
|
|||||||
cmd: this.JDWP.Commands.lineTable(methodinfo.owningclass, methodinfo),
|
cmd: this.JDWP.Commands.lineTable(methodinfo.owningclass, methodinfo),
|
||||||
})
|
})
|
||||||
.then(function (linetable, methodinfo) {
|
.then(function (linetable, methodinfo) {
|
||||||
|
// if the request failed, just return a blank table
|
||||||
|
if (linetable.errorcode) {
|
||||||
|
linetable = {
|
||||||
|
errorcode: linetable.errorcode,
|
||||||
|
start: '00000000000000000000000000000000',
|
||||||
|
end: '00000000000000000000000000000000',
|
||||||
|
lines:[],
|
||||||
|
}
|
||||||
|
}
|
||||||
// the linetable does not correlate code indexes with line numbers
|
// the linetable does not correlate code indexes with line numbers
|
||||||
// - location searching relies on the table being ordered by code indexes
|
// - location searching relies on the table being ordered by code indexes
|
||||||
linetable.lines.sort(function (a, b) {
|
linetable.lines.sort(function (a, b) {
|
||||||
|
|||||||
11
src/jdwp.js
11
src/jdwp.js
@@ -1,5 +1,5 @@
|
|||||||
const $ = require('./jq-promise');
|
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
|
JDWP - The Java Debug Wire Protocol
|
||||||
*/
|
*/
|
||||||
@@ -96,8 +96,8 @@ function _JDWP() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.errorcode != 0) {
|
if (this.errorcode !== 0) {
|
||||||
console.error("Command failed: error " + this.errorcode, this);
|
E(`JDWP command failed '${this.command.name}'. Error ${this.errorcode}`, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.errorcode && this.command && this.command.replydecodefn) {
|
if (!this.errorcode && this.command && this.command.replydecodefn) {
|
||||||
@@ -109,7 +109,10 @@ function _JDWP() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.decoded = {empty:true};
|
this.decoded = {
|
||||||
|
empty: true,
|
||||||
|
errorcode: this.errorcode,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.decodereply = function(ths,s) {
|
this.decodereply = function(ths,s) {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ var Deferred = exports.Deferred = function(p, parent) {
|
|||||||
var faildef = $.Deferred(null, this);
|
var faildef = $.Deferred(null, this);
|
||||||
var p = this._promise.catch(function(a) {
|
var p = this._promise.catch(function(a) {
|
||||||
if (a.stack) {
|
if (a.stack) {
|
||||||
console.error(a.stack);
|
util.E(a.stack);
|
||||||
a = [a];
|
a = [a];
|
||||||
}
|
}
|
||||||
if (this.def._context === null && this.def._parent)
|
if (this.def._context === null && this.def._parent)
|
||||||
|
|||||||
11
src/util.js
11
src/util.js
@@ -1,13 +1,18 @@
|
|||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
|
||||||
var nofn = function () { };
|
var nofn = function () { };
|
||||||
var D = exports.D = console.log.bind(console);
|
const messagePrintCallbacks = new Set();
|
||||||
var E = exports.E = console.error.bind(console);
|
var D = exports.D = (...args) => (console.log(...args), messagePrintCallbacks.forEach(cb => cb(...args)))
|
||||||
var W = exports.W = console.warn.bind(console);
|
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 DD = nofn, cl = D, printf = D;
|
||||||
var print_jdwp_data = nofn;// _print_jdwp_data;
|
var print_jdwp_data = nofn;// _print_jdwp_data;
|
||||||
var print_packet = nofn;//_print_packet;
|
var print_packet = nofn;//_print_packet;
|
||||||
|
|
||||||
|
exports.onMessagePrint = function(cb) {
|
||||||
|
messagePrintCallbacks.add(cb);
|
||||||
|
}
|
||||||
|
|
||||||
Array.first = function (arr, fn, defaultvalue) {
|
Array.first = function (arr, fn, defaultvalue) {
|
||||||
var idx = Array.indexOfFirst(arr, fn);
|
var idx = Array.indexOfFirst(arr, fn);
|
||||||
return idx < 0 ? defaultvalue : arr[idx];
|
return idx < 0 ? defaultvalue : arr[idx];
|
||||||
|
|||||||
Reference in New Issue
Block a user