first cut of "server-ready-action" feature

This commit is contained in:
Andre Weinand 2019-02-21 18:30:42 +01:00
parent b05c75cdb8
commit ef6d8eb11d
8 changed files with 230 additions and 0 deletions

View file

@ -0,0 +1,5 @@
src/**
tsconfig.json
out/**
extension.webpack.config.js
yarn.lock

View file

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
const withDefaults = require('../shared.webpack.config');
module.exports = withDefaults({
context: __dirname,
entry: {
extension: './src/extension.ts',
},
resolve: {
mainFields: ['module', 'main']
}
});

View file

@ -0,0 +1,74 @@
{
"name": "debug-auto-launch",
"displayName": "%displayName%",
"description": "%description%",
"version": "1.0.0",
"publisher": "vscode",
"engines": {
"vscode": "^1.32.0"
},
"activationEvents": [
"onDebugResolve"
],
"main": "./out/extension",
"scripts": {
"compile": "gulp compile-extension:debug-server-ready",
"watch": "gulp watch-extension:debug-server-ready"
},
"contributes": {
"debuggers": [
{
"type": "node",
"configurationAttributes": {
"launch": {
"properties": {
"serverReadyAction": {
"type": "object",
"markdownDescription": "Server Ready options.",
"default": {
"action": "openExternally"
},
"properties": {
"pattern": {
"type": "string",
"markdownDescription": "Server is ready if this pattern appears on the debug console. The first group must include the port number.",
"default": "listening on port ([0-9]+)"
},
"uriFormat": {
"type": "string",
"markdownDescription": "A format string used when constructing the URI. The first '%s' is substituted with the port number.",
"default": "http://localhost:%s"
},
"action": {
"type": "string",
"enum": [
"openExternally",
"debugWithChrome"
],
"enumDescriptions": [
"Open URI externally.",
"Start debugging with the Debugger for Chrome."
],
"markdownDescription": "Determines what to do with when the server is ready.",
"default": "openExternally"
},
"webRoot": {
"type": "string",
"markdownDescription": "Literally passed to chrome debug configuration.",
"default": "${workspaceFolder}"
}
}
}
}
}
}
}
]
},
"dependencies": {
"vscode-nls": "^4.0.0"
},
"devDependencies": {
"@types/node": "8.0.33"
}
}

View file

@ -0,0 +1,4 @@
{
"displayName": "Server Ready Action",
"description": "Open URI in browser if server under debugging is ready."
}

View file

@ -0,0 +1,97 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
//import * as nls from 'vscode-nls';
import * as util from 'util';
const trackers = new Set<string>();
const PATTERN = 'listening on.* (https?://\\S+|[0-9]+)'; // matches "listening on port 3000" or "Now listening on: https://localhost:5001"
const URI_FORMAT = 'http://localhost:%s';
const WEB_ROOT = '${workspaceFolder}';
interface ServerReadyAction {
pattern: string;
action?: 'openExternally' | 'debugWithChrome';
urlFormat?: string;
webRoot?: string;
}
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('*', {
resolveDebugConfiguration(_folder: vscode.WorkspaceFolder | undefined, debugConfiguration: vscode.DebugConfiguration) {
const args: ServerReadyAction = debugConfiguration.serverReadyAction;
if (debugConfiguration.type && args) {
startTrackerForType(context, debugConfiguration.type);
}
return debugConfiguration;
}
}));
}
function startTrackerForType(context: vscode.ExtensionContext, type: string) {
if (!trackers.has(type)) {
trackers.add(type);
// scan debug console output for a PORT message
context.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory(type, {
createDebugAdapterTracker(session: vscode.DebugSession) {
const args: ServerReadyAction = session.configuration.serverReadyAction;
if (args) {
const regexp = new RegExp(args.pattern || PATTERN);
let hasFired = false;
return {
onDidSendMessage: m => {
if (!hasFired && m.type === 'event' && m.event === 'output' && m.body.output) {
const result = regexp.exec(m.body.output);
if (result && result.length === 2) {
openExternalWithString(session, result[1]);
hasFired = true;
}
}
}
};
}
return undefined;
}
}));
}
}
function openExternalWithString(session: vscode.DebugSession, portOrUriString: string) {
if (portOrUriString) {
if (/^[0-9]+$/.test(portOrUriString)) {
const args: ServerReadyAction = session.configuration.serverReadyAction;
portOrUriString = util.format(args.urlFormat || URI_FORMAT, portOrUriString);
}
openExternalWithUri(session, portOrUriString);
}
}
function openExternalWithUri(session: vscode.DebugSession, uri: string) {
const args: ServerReadyAction = session.configuration.serverReadyAction;
switch (args.action || 'openExternally') {
case 'openExternally':
vscode.env.openExternal(vscode.Uri.parse(uri));
break;
case 'debugWithChrome':
vscode.debug.startDebugging(session.workspaceFolder, {
type: 'chrome',
name: 'Chrome Debug',
request: 'launch',
url: uri,
webRoot: args.webRoot || WEB_ROOT
});
break;
default:
// not supported
break;
}
}

View file

@ -0,0 +1,7 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path='../../../../src/vs/vscode.d.ts'/>
/// <reference types='@types/node'/>

View file

@ -0,0 +1,10 @@
{
"extends": "../shared.tsconfig.json",
"compilerOptions": {
"outDir": "./out",
"downlevelIteration": true
},
"include": [
"src/**/*"
]
}

View file

@ -0,0 +1,13 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@8.0.33":
version "8.0.33"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd"
integrity sha512-vmCdO8Bm1ExT+FWfC9sd9r4jwqM7o97gGy2WBshkkXbf/2nLAJQUrZfIhw27yVOtLUev6kSZc4cav/46KbDd8A==
vscode-nls@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==