More configuration settings

Added autoStartADB and logcatPort  launch config settings
Moved AndroidContentProvider into it's own file.
This commit is contained in:
adelphes
2017-02-01 12:22:25 +00:00
parent e23fc698a2
commit a47de40088
5 changed files with 110 additions and 76 deletions

View File

@@ -1,20 +1,15 @@
// The module 'vscode' contains the VS Code extensibility API // The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below // Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode'); const vscode = require('vscode');
const { AndroidContentProvider, openLogcatWindow } = require('./src/logcat'); const { AndroidContentProvider } = require('./src/contentprovider');
const { openLogcatWindow } = require('./src/logcat');
function getADBPort() { function getADBPort() {
var adbPort = 5037; var defaultPort = 5037;
// there's surely got to be a better way than this... var adbPort = AndroidContentProvider.getLaunchConfigSetting('adbPort', defaultPort);
var configs = vscode.workspace.getConfiguration('launch.configurations'); if (typeof adbPort === 'number' && adbPort === (adbPort|0))
for (var i=0,config; config=configs.get(''+i); i++) { return adbPort;
if (config.type!=='android') continue; return defaultPort;
if (config.request!=='launch') continue;
if (typeof config.adbPort === 'number' && config.adbPort === (config.adbPort|0))
adbPort = config.adbPort;
break;
}
return adbPort;
} }
// this method is called when your extension is activated // this method is called when your extension is activated

View File

@@ -66,6 +66,16 @@
"description": "Port number to connect to the local ADB (Android Debug Bridge) instance. Default: 5037", "description": "Port number to connect to the local ADB (Android Debug Bridge) instance. Default: 5037",
"default": 5037 "default": 5037
}, },
"autoStartADB": {
"type": "boolean",
"description": "Automatically launch 'adb start-server' if not already started. Default: true",
"default": true
},
"logcatPort": {
"type": "integer",
"description": "Port number to use for the internal logcat websocket link. Changes to this value only apply when the extension is restarted. Default: 7038",
"default": 7038
},
"staleBuild": { "staleBuild": {
"type": "string", "type": "string",
"description": "Launch behaviour if source files have been saved after the APK was built. One of: [\"ignore\" \"warn\" \"stop\"]. Default: \"warn\"", "description": "Launch behaviour if source files have been saved after the APK was built. One of: [\"ignore\" \"warn\" \"stop\"]. Default: \"warn\"",

78
src/contentprovider.js Normal file
View File

@@ -0,0 +1,78 @@
'use strict'
// vscode stuff
const { workspace, EventEmitter, Uri } = require('vscode');
class AndroidContentProvider /*extends TextDocumentContentProvider*/ {
constructor() {
this._docs = {}; // hashmap<url, LogcatContent>
this._onDidChange = new EventEmitter();
}
dispose() {
this._onDidChange.dispose();
}
/**
* An event to signal a resource has changed.
*/
get onDidChange() {
return this._onDidChange.event;
}
/**
* Provide textual content for a given uri.
*
* The editor will use the returned string-content to create a readonly
* [document](TextDocument). Resources allocated should be released when
* the corresponding document has been [closed](#workspace.onDidCloseTextDocument).
*
* @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for.
* @param token A cancellation token.
* @return A string or a thenable that resolves to such.
*/
provideTextDocumentContent(uri/*: Uri*/, token/*: CancellationToken*/)/*: string | Thenable<string>;*/ {
var doc = this._docs[uri];
if (doc) return this._docs[uri].content;
switch (uri.authority) {
// android-dev-ext://logcat/read?<deviceid>
case 'logcat': return this.provideLogcatDocumentContent(uri);
}
throw new Error('Document Uri not recognised');
}
provideLogcatDocumentContent(uri) {
// LogcatContent depends upon AndroidContentProvider, so we must delay-load this
const { LogcatContent } = require('./logcat');
var doc = this._docs[uri] = new LogcatContent(this, uri);
return doc.content;
}
}
// the statics
AndroidContentProvider.SCHEME = 'android-dev-ext';
AndroidContentProvider.register = (ctx, workspace) => {
var provider = new AndroidContentProvider();
var registration = workspace.registerTextDocumentContentProvider(AndroidContentProvider.SCHEME, provider);
ctx.subscriptions.push(registration);
ctx.subscriptions.push(provider);
}
AndroidContentProvider.getReadLogcatUri = (deviceId) => {
var uri = Uri.parse(`${AndroidContentProvider.SCHEME}://logcat/logcat-${deviceId}.txt`);
return uri.with({
query: deviceId
});
}
AndroidContentProvider.getLaunchConfigSetting = (name, defvalue) => {
// there's surely got to be a better way than this...
var configs = workspace.getConfiguration('launch.configurations');
for (var i=0,config; config=configs.get(''+i); i++) {
if (config.type!=='android') continue;
if (config.request!=='launch') continue;
if (config[name]) return config[name];
break;
}
return defvalue;
}
exports.AndroidContentProvider = AndroidContentProvider;

View File

@@ -312,7 +312,7 @@ class AndroidDebugSession extends DebugSession {
.then(err => { .then(err => {
// if adb is not running, see if we can start it ourselves using ANDROID_HOME (and a sensible port number) // if adb is not running, see if we can start it ourselves using ANDROID_HOME (and a sensible port number)
var adbport = ws_proxy.adbport; var adbport = ws_proxy.adbport;
if (err && process.env.ANDROID_HOME && typeof adbport === 'number' && adbport > 0 && adbport < 65536) { if (err && args.autoStartADB!==false && process.env.ANDROID_HOME && typeof adbport === 'number' && adbport > 0 && adbport < 65536) {
var adbpath = path.join(process.env.ANDROID_HOME, 'platform-tools', /^win/.test(process.platform)?'adb.exe':'adb'); var adbpath = path.join(process.env.ANDROID_HOME, 'platform-tools', /^win/.test(process.platform)?'adb.exe':'adb');
var adbargs = ['-P',''+adbport,'start-server']; var adbargs = ['-P',''+adbport,'start-server'];
try { try {
@@ -396,7 +396,7 @@ class AndroidDebugSession extends DebugSession {
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'));
// more info for adb connect errors // more info for adb connect errors
if (/^ADB server is not running/.test(e.msg)) { if (/^ADB server is not running/.test(e.msg)) {
this.LOG('Make sure the Android SDK tools are installed and run:'); this.LOG('Make sure the Android SDK Platform Tools are installed and run:');
this.LOG(' adb start-server'); this.LOG(' adb start-server');
this.LOG('If you are running ADB on a non-default port, also make sure the adbPort value in your launch.json is correct.'); this.LOG('If you are running ADB on a non-default port, also make sure the adbPort value in your launch.json is correct.');
} }

View File

@@ -8,6 +8,7 @@ const path = require('path');
const WebSocketServer = require('ws').Server; const WebSocketServer = require('ws').Server;
// our stuff // our stuff
const { ADBClient } = require('./adbclient'); const { ADBClient } = require('./adbclient');
const { AndroidContentProvider } = require('./contentprovider');
const $ = require('./jq-promise'); const $ = require('./jq-promise');
const { D } = require('./util'); const { D } = require('./util');
@@ -171,19 +172,29 @@ class LogcatContent {
LogcatContent.byLogcatID = {}; LogcatContent.byLogcatID = {};
LogcatContent.initWebSocketServer = function () { LogcatContent.initWebSocketServer = function () {
if (LogcatContent._wssdone) { if (LogcatContent._wssdone) {
// already inited // already inited
return LogcatContent._wssdone; return LogcatContent._wssdone;
} }
// retrieve the logcat websocket port
var default_wssport = 7038;
var wssport = AndroidContentProvider.getLaunchConfigSetting('logcatPort', default_wssport);
if (typeof wssport !== 'number' || wssport <= 0 || wssport >= 65536 || wssport !== (wssport|0))
wssport = default_wssport;
LogcatContent._wssdone = $.Deferred(); LogcatContent._wssdone = $.Deferred();
({ ({
wss: null, wss: null,
port: 31100, startport: wssport,
port: wssport,
retries: 0, retries: 0,
tryCreateWSS() { tryCreateWSS() {
this.wss = new WebSocketServer({ host: '127.0.0.1', port: this.port }, () => { this.wss = new WebSocketServer({ host: '127.0.0.1', port: this.port }, () => {
// success - save the info and resolve the deferred // success - save the info and resolve the deferred
LogcatContent._wssport = this.port; LogcatContent._wssport = this.port;
LogcatContent._wssstartport = this.startport;
LogcatContent._wss = this.wss; LogcatContent._wss = this.wss;
this.wss.on('connection', client => { this.wss.on('connection', client => {
// the client uses the url path to signify which logcat data it wants // the client uses the url path to signify which logcat data it wants
@@ -216,66 +227,6 @@ LogcatContent.initWebSocketServer = function () {
return LogcatContent._wssdone; return LogcatContent._wssdone;
} }
class AndroidContentProvider /*extends TextDocumentContentProvider*/ {
constructor() {
this._logs = {}; // hashmap<url, LogcatContent>
this._onDidChange = new EventEmitter();
}
dispose() {
this._onDidChange.dispose();
}
/**
* An event to signal a resource has changed.
*/
get onDidChange() {
return this._onDidChange.event;
}
/**
* Provide textual content for a given uri.
*
* The editor will use the returned string-content to create a readonly
* [document](TextDocument). Resources allocated should be released when
* the corresponding document has been [closed](#workspace.onDidCloseTextDocument).
*
* @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for.
* @param token A cancellation token.
* @return A string or a thenable that resolves to such.
*/
provideTextDocumentContent(uri/*: Uri*/, token/*: CancellationToken*/)/*: string | Thenable<string>;*/ {
var doc = this._logs[uri];
if (doc) return this._logs[uri].content;
switch (uri.authority) {
// android-dev-ext://logcat/read?<deviceid>
case 'logcat': return this.provideLogcatDocumentContent(uri);
}
throw new Error('Document Uri not recognised');
}
provideLogcatDocumentContent(uri) {
var doc = this._logs[uri] = new LogcatContent(this, uri);
return doc.content;
}
}
// the statics
AndroidContentProvider.SCHEME = 'android-dev-ext';
AndroidContentProvider.register = (ctx, workspace) => {
var provider = new AndroidContentProvider();
var registration = workspace.registerTextDocumentContentProvider(AndroidContentProvider.SCHEME, provider);
ctx.subscriptions.push(registration);
ctx.subscriptions.push(provider);
}
AndroidContentProvider.getReadLogcatUri = (deviceId) => {
var uri = Uri.parse(`${AndroidContentProvider.SCHEME}://logcat/logcat-${deviceId}.txt`);
return uri.with({
query: deviceId
});
}
function openLogcatWindow(vscode) { function openLogcatWindow(vscode) {
new ADBClient().list_devices().then(devices => { new ADBClient().list_devices().then(devices => {
switch(devices.length) { switch(devices.length) {
@@ -314,5 +265,5 @@ function openLogcatWindow(vscode) {
}); });
} }
exports.AndroidContentProvider = AndroidContentProvider; exports.LogcatContent = LogcatContent;
exports.openLogcatWindow = openLogcatWindow; exports.openLogcatWindow = openLogcatWindow;