Fix #280 - show a quickpick when there are multiple possible tabs to attach to

This commit is contained in:
Rob Lourens 2017-04-19 21:07:32 -07:00
Родитель 7ee29e6036
Коммит 017590aeed
6 изменённых файлов: 67 добавлений и 7 удалений

Просмотреть файл

@ -21,8 +21,8 @@
],
"license": "SEE LICENSE IN LICENSE.txt",
"dependencies": {
"vscode-chrome-debug-core": "3.14.18",
"vscode-debugadapter": "1.18.0-pre.5"
"vscode-chrome-debug-core": "3.15.0",
"vscode-debugadapter": "1.19.0-pre.0"
},
"devDependencies": {
"@types/mocha": "^2.2.35",
@ -50,6 +50,7 @@
},
"main": "./out/src/extension",
"activationEvents": [
"onCommand:extension.chrome-debug.startSession",
"onCommand:extension.chrome-debug.toggleSkippingFile"
],
"scripts": {
@ -90,6 +91,7 @@
"runtime": "node",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"languages": [ "javascript", "typescript", "javascriptreact", "typescriptreact" ],
"startSessionCommand": "extension.chrome-debug.startSession",
"initialConfigurations": [
{
"type": "chrome",

Просмотреть файл

@ -4,11 +4,11 @@
import {ChromeDebugSession, logger, UrlPathTransformer, BaseSourceMapTransformer} from 'vscode-chrome-debug-core';
import * as path from 'path';
import {targetFilter} from './utils';
import {ChromeDebugAdapter} from './chromeDebugAdapter';
const EXTENSION_NAME = 'debugger-for-chrome';
const targetFilter = target => target && (!target.type || target.type === 'page');
// Injected by webpack
declare let VERSION: string;

Просмотреть файл

@ -5,8 +5,11 @@
import * as vscode from 'vscode';
import * as Core from 'vscode-chrome-debug-core';
import {targetFilter} from './utils';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('extension.chrome-debug.toggleSkippingFile', toggleSkippingFile));
context.subscriptions.push(vscode.commands.registerCommand('extension.chrome-debug.startSession', startSession));
}
export function deactivate() {
@ -21,3 +24,54 @@ function toggleSkippingFile(path: string): void {
const args: Core.IToggleSkipFileStatusArgs = typeof path === 'string' ? { path } : { sourceReference: path };
vscode.commands.executeCommand('workbench.customDebugRequest', 'toggleSkipFileStatus', args);
}
interface StartSessionResult {
status: 'ok' | 'initialConfiguration' | 'saveConfiguration';
content?: string; // launch.json content for 'save'
};
async function startSession(config: any): Promise<StartSessionResult> {
if (config.request === 'attach') {
const discovery = new Core.chromeTargetDiscoveryStrategy.ChromeTargetDiscovery(
new Core.NullLogger(), new Core.telemetry.NullTelemetryReporter());
const targets = await discovery.getAllTargets(config.address || '127.0.0.1', config.port, targetFilter, config.url);
if (targets.length > 1) {
const selectedTarget = await pickTarget(targets);
if (!selectedTarget) {
// Quickpick canceled, bail
return;
}
config.websocketUrl = selectedTarget.websocketDebuggerUrl;
}
}
vscode.commands.executeCommand('vscode.startDebug', config);
return Promise.resolve<StartSessionResult>({ status: 'ok' });
}
interface ITargetQuickPickItem extends vscode.QuickPickItem {
websocketDebuggerUrl: string;
}
async function pickTarget(targets: Core.chromeConnection.ITarget[]): Promise<ITargetQuickPickItem> {
const items = targets.map(target => (<ITargetQuickPickItem>{
label: unescapeTargetTitle(target.title),
detail: target.url,
websocketDebuggerUrl: target.webSocketDebuggerUrl
}));
const selected = await vscode.window.showQuickPick(items, { placeHolder: 'Select a tab', matchOnDescription: true, matchOnDetail: true });
return selected;
}
function unescapeTargetTitle(title: string): string {
return title
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&#39;/g, `'`)
.replace(/&quot;/g, '"');
}

Просмотреть файл

@ -3,7 +3,7 @@
*--------------------------------------------------------*/
import * as path from 'path';
import {utils as coreUtils} from 'vscode-chrome-debug-core';
import {utils as coreUtils, chromeConnection} from 'vscode-chrome-debug-core';
const WIN_APPDATA = process.env.LOCALAPPDATA || '/';
const DEFAULT_CHROME_PATH = {
@ -63,3 +63,6 @@ export class DebounceHelper {
fn();
}
}
export const targetFilter: chromeConnection.ITargetFilter =
target => target && (!target.type || target.type === 'page');

Просмотреть файл

@ -3,7 +3,7 @@
*--------------------------------------------------------*/
import {DebugProtocol} from 'vscode-debugprotocol';
import {ChromeConnection, ISourceMapPathOverrides} from 'vscode-chrome-debug-core';
import {chromeConnection, ISourceMapPathOverrides} from 'vscode-chrome-debug-core';
import * as mockery from 'mockery';
import {EventEmitter} from 'events';
@ -26,7 +26,7 @@ class MockChromeDebugSession {
const MODULE_UNDER_TEST = '../src/chromeDebugAdapter';
suite('ChromeDebugAdapter', () => {
let mockChromeConnection: Mock<ChromeConnection>;
let mockChromeConnection: Mock<chromeConnection.ChromeConnection>;
let mockEventEmitter: EventEmitter;
let mockChrome: IMockChromeConnectionAPI;
@ -37,7 +37,7 @@ suite('ChromeDebugAdapter', () => {
mockery.enable({ useCleanCache: true, warnOnReplace: false, warnOnUnregistered: false });
// Create a ChromeConnection mock with .on and .attach. Tests can fire events via mockEventEmitter
mockChromeConnection = Mock.ofType(ChromeConnection, MockBehavior.Strict);
mockChromeConnection = Mock.ofType(chromeConnection.ChromeConnection, MockBehavior.Strict);
mockChrome = getMockChromeConnectionApi();
mockEventEmitter = mockChrome.mockEventEmitter;
mockChromeConnection

Просмотреть файл

@ -1,6 +1,7 @@
<!doctype html>
<html>
<head>
<title>testapp</title>
<script src="out/client with space/test1.js?blah"></script>
<script src="out/client%20with%20space/test2.js"></script>
<script>