add browser/webworker support
This commit is contained in:
Родитель
c2dc113ef3
Коммит
354c0e93c9
|
@ -1,6 +1,8 @@
|
|||
.DS_Store
|
||||
node_modules/
|
||||
out/
|
||||
out
|
||||
dist
|
||||
node_modules
|
||||
.vscode-test/
|
||||
npm-debug.log
|
||||
mock-debug.txt
|
||||
*.vsix
|
||||
.DS_Store
|
||||
|
|
|
@ -5,15 +5,29 @@
|
|||
"name": "Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"${workspaceFolder}/sampleworkspace"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm: watch"
|
||||
},
|
||||
{
|
||||
"name": "Web Extension",
|
||||
"type": "pwa-extensionHost",
|
||||
"debugWebWorkerHost": true,
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"${workspaceFolder}/sampleworkspace"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/web/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm: watch-web"
|
||||
},
|
||||
{
|
||||
"name": "Server",
|
||||
"type": "node",
|
||||
|
|
|
@ -1,18 +1,40 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "compile-web",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$ts-webpack",
|
||||
"$tslint-webpack"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch-web",
|
||||
"group": "build",
|
||||
"isBackground": true,
|
||||
"problemMatcher": [
|
||||
"$ts-webpack-watch",
|
||||
"$tslint-webpack-watch"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
|
||||
## 0.43.0
|
||||
* Added context menu action "Show as Hex" to integer variables in Variables view
|
||||
* Added new run option "namedPipeServer" for debug adapter in extension.ts
|
||||
* Using new extension API for passing the "noDebug" option to "vscode.debug.startDebugging"
|
||||
* Add context menu action "Show as Hex" to integer variables in Variables view
|
||||
* Add new run option "namedPipeServer" for debug adapter in extension.ts
|
||||
* Use new extension API for passing the "noDebug" option to "vscode.debug.startDebugging"
|
||||
* Support to run Mock Debug in the browser/web worker
|
||||
|
||||
## 0.42.2
|
||||
* Project hygiene: get rid of all warnings
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* 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';
|
||||
|
||||
//@ts-check
|
||||
/** @typedef {import('webpack').Configuration} WebpackConfig **/
|
||||
|
||||
const path = require('path');
|
||||
|
||||
module.exports = /** @type WebpackConfig */ {
|
||||
context: path.dirname(__dirname),
|
||||
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
|
||||
target: 'webworker', // extensions run in a webworker context
|
||||
entry: {
|
||||
extension: './src/web/extension.ts',
|
||||
},
|
||||
resolve: {
|
||||
mainFields: ['module', 'main'],
|
||||
extensions: ['.ts', '.js'], // support ts-files and js-files
|
||||
alias: {
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
// configure TypeScript loader:
|
||||
// * enable sources maps for end-to-end source maps
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
compilerOptions: {
|
||||
'sourceMap': true,
|
||||
'declaration': false
|
||||
}
|
||||
}
|
||||
}]
|
||||
}]
|
||||
},
|
||||
externals: {
|
||||
'vscode': 'commonjs vscode', // ignored because it doesn't exist
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
output: {
|
||||
filename: 'extension.js',
|
||||
path: path.join(__dirname, '../dist/web'),
|
||||
libraryTarget: 'commonjs'
|
||||
},
|
||||
devtool: 'source-map'
|
||||
};
|
335
package.json
335
package.json
|
@ -1,166 +1,173 @@
|
|||
{
|
||||
"name": "mock-debug",
|
||||
"displayName": "Mock Debug",
|
||||
"version": "0.42.2",
|
||||
"publisher": "andreweinand",
|
||||
"description": "Starter extension for developing debug adapters for VS Code.",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation",
|
||||
"email": "aweinand@microsoft.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"multi-root ready"
|
||||
],
|
||||
"engines": {
|
||||
"vscode": "^1.46.0"
|
||||
},
|
||||
"icon": "images/mock-debug-icon.png",
|
||||
"categories": [
|
||||
"Debuggers"
|
||||
],
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-mock-debug.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Microsoft/vscode-mock-debug/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "yarn run compile",
|
||||
"compile": "tsc -p ./",
|
||||
"lint": "eslint src --ext ts",
|
||||
"watch": "tsc -watch -p ./",
|
||||
"pretest": "yarn run compile && yarn run lint",
|
||||
"test": "node ./out/test/runTest.js",
|
||||
"package": "vsce package",
|
||||
"publish": "vsce publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"await-notify": "1.0.1",
|
||||
"vscode-debugadapter": "1.41.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/vscode": "^1.48.0",
|
||||
"@types/glob": "^7.1.3",
|
||||
"@types/mocha": "^8.0.0",
|
||||
"@types/node": "^14.0.27",
|
||||
"eslint": "^7.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^3.8.0",
|
||||
"@typescript-eslint/parser": "^3.8.0",
|
||||
"glob": "^7.1.6",
|
||||
"mocha": "^8.0.1",
|
||||
"typescript": "^3.8.3",
|
||||
"vscode-debugadapter-testsupport": "1.41.0",
|
||||
"vsce": "1.78.0"
|
||||
},
|
||||
"main": "./out/extension",
|
||||
"activationEvents": [
|
||||
"onDebug",
|
||||
"onDebugDynamicConfigurations:mock",
|
||||
"onCommand:extension.mock-debug.getProgramName",
|
||||
"onCommand:extension.mock-debug.runEditorContents",
|
||||
"onCommand:extension.mock-debug.debugEditorContents"
|
||||
],
|
||||
"contributes": {
|
||||
"menus": {
|
||||
"editor/title": [
|
||||
{
|
||||
"command": "extension.mock-debug.runEditorContents",
|
||||
"when": "resourceLangId == markdown",
|
||||
"group": "1_run@10"
|
||||
},
|
||||
{
|
||||
"command": "extension.mock-debug.debugEditorContents",
|
||||
"when": "resourceLangId == markdown",
|
||||
"group": "1_run@20"
|
||||
}
|
||||
],
|
||||
"debug/variables/context": [
|
||||
{
|
||||
"command": "extension.mock-debug.showAsHex",
|
||||
"when": "debugConfigurationType == 'mock' && debugProtocolVariableMenuContext == 'simple'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "extension.mock-debug.debugEditorContents",
|
||||
"title": "Debug File",
|
||||
"icon": "$(debug-alt)"
|
||||
},
|
||||
{
|
||||
"command": "extension.mock-debug.runEditorContents",
|
||||
"title": "Run File",
|
||||
"icon": "$(play)"
|
||||
},
|
||||
{
|
||||
"command": "extension.mock-debug.showAsHex",
|
||||
"title": "Show as Hex"
|
||||
}
|
||||
],
|
||||
"breakpoints": [
|
||||
{
|
||||
"language": "markdown"
|
||||
}
|
||||
],
|
||||
"debuggers": [
|
||||
{
|
||||
"type": "mock",
|
||||
"label": "Mock Debug",
|
||||
"program": "./out/debugAdapter.js",
|
||||
"runtime": "node",
|
||||
"configurationAttributes": {
|
||||
"launch": {
|
||||
"required": [
|
||||
"program"
|
||||
],
|
||||
"properties": {
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a text file.",
|
||||
"default": "${workspaceFolder}/${command:AskForProgramName}"
|
||||
},
|
||||
"stopOnEntry": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically stop after launch.",
|
||||
"default": true
|
||||
},
|
||||
"trace": {
|
||||
"type": "boolean",
|
||||
"description": "Enable logging of the Debug Adapter Protocol.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialConfigurations": [
|
||||
{
|
||||
"type": "mock",
|
||||
"request": "launch",
|
||||
"name": "Ask for file name",
|
||||
"program": "${workspaceFolder}/${command:AskForProgramName}",
|
||||
"stopOnEntry": true
|
||||
}
|
||||
],
|
||||
"configurationSnippets": [
|
||||
{
|
||||
"label": "Mock Debug: Launch",
|
||||
"description": "A new configuration for 'debugging' a user selected markdown file.",
|
||||
"body": {
|
||||
"type": "mock",
|
||||
"request": "launch",
|
||||
"name": "Ask for file name",
|
||||
"program": "^\"\\${workspaceFolder}/\\${command:AskForProgramName}\"",
|
||||
"stopOnEntry": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"variables": {
|
||||
"AskForProgramName": "extension.mock-debug.getProgramName"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"name": "mock-debug",
|
||||
"displayName": "Mock Debug",
|
||||
"version": "0.43.0",
|
||||
"publisher": "andreweinand",
|
||||
"description": "Starter extension for developing debug adapters for VS Code.",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation",
|
||||
"email": "aweinand@microsoft.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"multi-root ready"
|
||||
],
|
||||
"engines": {
|
||||
"vscode": "^1.46.0"
|
||||
},
|
||||
"icon": "images/mock-debug-icon.png",
|
||||
"categories": [
|
||||
"Debuggers"
|
||||
],
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-mock-debug.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Microsoft/vscode-mock-debug/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "yarn run compile",
|
||||
"compile": "tsc -p ./",
|
||||
"lint": "eslint src --ext ts",
|
||||
"watch": "tsc -watch -p ./",
|
||||
"pretest": "yarn run compile && yarn run lint",
|
||||
"test": "node ./out/test/runTest.js",
|
||||
"package": "vsce package",
|
||||
"publish": "vsce publish",
|
||||
"compile-web": "webpack --devtool nosources-source-map --config ./build/web-extension.webpack.config.js",
|
||||
"watch-web": "webpack --watch --devtool nosources-source-map --info-verbosity verbose --config ./build/web-extension.webpack.config.js",
|
||||
"package-web": "webpack --mode production --watch --config ./build/web-extension.webpack.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"await-notify": "1.0.1",
|
||||
"vscode-debugadapter": "1.42.0-pre.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/vscode": "^1.48.0",
|
||||
"@types/glob": "^7.1.3",
|
||||
"@types/mocha": "^8.0.0",
|
||||
"@types/node": "^14.0.27",
|
||||
"eslint": "^7.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^3.8.0",
|
||||
"@typescript-eslint/parser": "^3.8.0",
|
||||
"glob": "^7.1.6",
|
||||
"mocha": "^8.0.1",
|
||||
"typescript": "^3.8.3",
|
||||
"vscode-debugadapter-testsupport": "1.41.0",
|
||||
"vsce": "^1.79.5",
|
||||
"ts-loader": "^8.0.2",
|
||||
"webpack": "^4.44.1",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
"main": "./out/extension",
|
||||
"browser": "./dist/web/extension.js",
|
||||
"activationEvents": [
|
||||
"onDebug",
|
||||
"onDebugDynamicConfigurations:mock",
|
||||
"onCommand:extension.mock-debug.getProgramName",
|
||||
"onCommand:extension.mock-debug.runEditorContents",
|
||||
"onCommand:extension.mock-debug.debugEditorContents"
|
||||
],
|
||||
"contributes": {
|
||||
"menus": {
|
||||
"editor/title": [
|
||||
{
|
||||
"command": "extension.mock-debug.runEditorContents",
|
||||
"when": "resourceLangId == markdown",
|
||||
"group": "1_run@10"
|
||||
},
|
||||
{
|
||||
"command": "extension.mock-debug.debugEditorContents",
|
||||
"when": "resourceLangId == markdown",
|
||||
"group": "1_run@20"
|
||||
}
|
||||
],
|
||||
"debug/variables/context": [
|
||||
{
|
||||
"command": "extension.mock-debug.showAsHex",
|
||||
"when": "debugConfigurationType == 'mock' && debugProtocolVariableMenuContext == 'simple'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "extension.mock-debug.debugEditorContents",
|
||||
"title": "Debug File",
|
||||
"icon": "$(debug-alt)"
|
||||
},
|
||||
{
|
||||
"command": "extension.mock-debug.runEditorContents",
|
||||
"title": "Run File",
|
||||
"icon": "$(play)"
|
||||
},
|
||||
{
|
||||
"command": "extension.mock-debug.showAsHex",
|
||||
"title": "Show as Hex"
|
||||
}
|
||||
],
|
||||
"breakpoints": [
|
||||
{
|
||||
"language": "markdown"
|
||||
}
|
||||
],
|
||||
"debuggers": [
|
||||
{
|
||||
"type": "mock",
|
||||
"label": "Mock Debug",
|
||||
"program": "./out/debugAdapter.js",
|
||||
"runtime": "node",
|
||||
"configurationAttributes": {
|
||||
"launch": {
|
||||
"required": [
|
||||
"program"
|
||||
],
|
||||
"properties": {
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a text file.",
|
||||
"default": "${workspaceFolder}/${command:AskForProgramName}"
|
||||
},
|
||||
"stopOnEntry": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically stop after launch.",
|
||||
"default": true
|
||||
},
|
||||
"trace": {
|
||||
"type": "boolean",
|
||||
"description": "Enable logging of the Debug Adapter Protocol.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialConfigurations": [
|
||||
{
|
||||
"type": "mock",
|
||||
"request": "launch",
|
||||
"name": "Ask for file name",
|
||||
"program": "${workspaceFolder}/${command:AskForProgramName}",
|
||||
"stopOnEntry": true
|
||||
}
|
||||
],
|
||||
"configurationSnippets": [
|
||||
{
|
||||
"label": "Mock Debug: Launch",
|
||||
"description": "A new configuration for 'debugging' a user selected markdown file.",
|
||||
"body": {
|
||||
"type": "mock",
|
||||
"request": "launch",
|
||||
"name": "Ask for file name",
|
||||
"program": "^\"\\${workspaceFolder}/\\${command:AskForProgramName}\"",
|
||||
"stopOnEntry": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"variables": {
|
||||
"AskForProgramName": "extension.mock-debug.getProgramName"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "mock",
|
||||
"request": "launch",
|
||||
"name": "Debug test.md",
|
||||
"program": "${workspaceFolder}/test.md",
|
||||
"stopOnEntry": true,
|
||||
"trace": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extensions.webWorker": true
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
# VS Code Mock Debug
|
||||
|
||||
Mock Debug allows to "debug" markdown files (like this).
|
||||
The text of the markdown is considered the "program to debug" and certain keywords trigger specific functionality:
|
||||
|
||||
* if debugging stops on a line, the line becomes a stack in the CALL STACK with the words shown as frames.
|
||||
* variables are synthetic
|
||||
|
||||
|
||||
Please note: breakpoints are only verified in an active debug session.
|
||||
|
||||
* if a line is empty or starts with '+' we don't allow to set a breakpoint but move the breakpoint down
|
||||
* if a line starts with '-' we don't allow to set a breakpoint but move the breakpoint up
|
||||
* a breakpoint on a line containing the word 'lazy' is not immediately verified, but only after hitting it once
|
||||
* Fire events if line has a breakpoint or the word 'exception' is found.
|
||||
* a line with the pattern `log(xxx)` logs `xxx` to the debug console. If "xxx" is `start` or `end`, a "log group" is started or ended.
|
||||
|
||||
|
||||
log(start)
|
||||
log(arbitrary line of text)
|
||||
log(start)
|
||||
log(arbitrary line of text level 2)
|
||||
log(start)
|
||||
log(arbitrary line of text level 3)
|
||||
log(start)
|
||||
log(arbitrary line of text level 4)
|
||||
log(start)
|
||||
log(arbitrary line of text level 5)
|
||||
log(another line of text level 5)
|
||||
log(end)
|
||||
log(another line of text level 4)
|
||||
log(end)
|
||||
log(another line of text level 3)
|
||||
log(end)
|
||||
log(another line of text level 2)
|
||||
log(end)
|
||||
log(another line of text)
|
||||
log(end)
|
|
@ -0,0 +1,138 @@
|
|||
/*---------------------------------------------------------
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { WorkspaceFolder, DebugConfiguration, ProviderResult, CancellationToken } from 'vscode';
|
||||
import { MockDebugSession } from './mockDebug';
|
||||
import { FileAccessor } from './mockRuntime';
|
||||
|
||||
export function activateMockDebug(context: vscode.ExtensionContext, factory?: vscode.DebugAdapterDescriptorFactory) {
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('extension.mock-debug.runEditorContents', (resource: vscode.Uri) => {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
type: 'mock',
|
||||
name: 'Run Editor Contents',
|
||||
request: 'launch',
|
||||
program: resource.fsPath
|
||||
}, {
|
||||
//noDebug: true
|
||||
});
|
||||
}),
|
||||
vscode.commands.registerCommand('extension.mock-debug.debugEditorContents', (resource: vscode.Uri) => {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
type: 'mock',
|
||||
name: 'Debug Editor Contents',
|
||||
request: 'launch',
|
||||
program: resource.fsPath
|
||||
});
|
||||
}),
|
||||
vscode.commands.registerCommand('extension.mock-debug.showAsHex', (variable) => {
|
||||
vscode.window.showInformationMessage(`${variable.container.name}: ${variable.variable.name}`);
|
||||
})
|
||||
);
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('extension.mock-debug.getProgramName', config => {
|
||||
return vscode.window.showInputBox({
|
||||
placeHolder: "Please enter the name of a markdown file in the workspace folder",
|
||||
value: "readme.md"
|
||||
});
|
||||
}));
|
||||
|
||||
// register a configuration provider for 'mock' debug type
|
||||
const provider = new MockConfigurationProvider();
|
||||
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('mock', provider));
|
||||
|
||||
// register a dynamic configuration provider for 'mock' debug type
|
||||
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('mock', {
|
||||
provideDebugConfigurations(folder: WorkspaceFolder | undefined): ProviderResult<DebugConfiguration[]> {
|
||||
return [
|
||||
{
|
||||
name: "Dynamic Launch",
|
||||
request: "launch",
|
||||
type: "node",
|
||||
program: "${file}"
|
||||
},
|
||||
{
|
||||
name: "Another Dynamic Launch",
|
||||
request: "launch",
|
||||
type: "node",
|
||||
program: "${file}"
|
||||
},
|
||||
{
|
||||
name: "Mock Launch",
|
||||
request: "launch",
|
||||
type: "node",
|
||||
program: "${file}"
|
||||
}
|
||||
];
|
||||
}
|
||||
}, vscode.DebugConfigurationProviderTriggerKind.Dynamic));
|
||||
|
||||
if (!factory) {
|
||||
factory = new InlineDebugAdapterFactory();
|
||||
}
|
||||
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('mock', factory));
|
||||
if ('dispose' in factory) {
|
||||
context.subscriptions.push(factory);
|
||||
}
|
||||
|
||||
// override VS Code's default implementation of the debug hover
|
||||
/*
|
||||
vscode.languages.registerEvaluatableExpressionProvider('markdown', {
|
||||
provideEvaluatableExpression(document: vscode.TextDocument, position: vscode.Position): vscode.ProviderResult<vscode.EvaluatableExpression> {
|
||||
const wordRange = document.getWordRangeAtPosition(position);
|
||||
return wordRange ? new vscode.EvaluatableExpression(wordRange) : undefined;
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
class MockConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
|
||||
/**
|
||||
* Massage a debug configuration just before a debug session is being launched,
|
||||
* e.g. add all missing attributes to the debug configuration.
|
||||
*/
|
||||
resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration> {
|
||||
|
||||
// if launch.json is missing or empty
|
||||
if (!config.type && !config.request && !config.name) {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor && editor.document.languageId === 'markdown') {
|
||||
config.type = 'mock';
|
||||
config.name = 'Launch';
|
||||
config.request = 'launch';
|
||||
config.program = '${file}';
|
||||
config.stopOnEntry = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.program) {
|
||||
return vscode.window.showInformationMessage("Cannot find a program to debug").then(_ => {
|
||||
return undefined; // abort launch
|
||||
});
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
export const workspaceFileAccessor: FileAccessor = {
|
||||
async readFile(path: string) {
|
||||
const uri = vscode.Uri.parse(path);
|
||||
const bytes = await vscode.workspace.fs.readFile(uri);
|
||||
const contents = Buffer.from(bytes).toString('utf8');
|
||||
return contents;
|
||||
}
|
||||
};
|
||||
|
||||
class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory {
|
||||
|
||||
createDebugAdapterDescriptor(_session: vscode.DebugSession): ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
return new vscode.DebugAdapterInlineImplementation(new MockDebugSession(workspaceFileAccessor));
|
||||
}
|
||||
}
|
|
@ -2,6 +2,59 @@
|
|||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
import { MockDebugSession } from './mockDebug';
|
||||
import { MockDebugSession } from './mockDebug';
|
||||
|
||||
MockDebugSession.run(MockDebugSession);
|
||||
import { readFileSync } from 'fs';
|
||||
import * as Net from 'net';
|
||||
import { FileAccessor } from './mockRuntime';
|
||||
|
||||
/*
|
||||
* Since the debug adapter runs as an external process, it has no access to VS Code API.
|
||||
*/
|
||||
const fsAccessor: FileAccessor = {
|
||||
async readFile(path: string): Promise<string> {
|
||||
const buffer = readFileSync(path);
|
||||
return buffer.toString();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* When the debug adapter is run as an external process,
|
||||
* the helper function DebugSession.run(...) takes care of everything.
|
||||
*/
|
||||
// MockDebugSession.run(MockDebugSession);
|
||||
|
||||
// ... but the helper is not flexible enough to deal with constructors with parameters.
|
||||
// So for now we use a modified copy of the helper:
|
||||
|
||||
// parse arguments
|
||||
let port = 0;
|
||||
const args = process.argv.slice(2);
|
||||
args.forEach(function (val, index, array) {
|
||||
const portMatch = /^--server=(\d{4,5})$/.exec(val);
|
||||
if (portMatch) {
|
||||
port = parseInt(portMatch[1], 10);
|
||||
}
|
||||
});
|
||||
|
||||
if (port > 0) {
|
||||
// start as a server
|
||||
console.error(`waiting for debug protocol on port ${port}`);
|
||||
Net.createServer((socket) => {
|
||||
console.error('>> accepted connection from client');
|
||||
socket.on('end', () => {
|
||||
console.error('>> client connection closed\n');
|
||||
});
|
||||
const session = new MockDebugSession(fsAccessor);
|
||||
session.setRunAsServer(true);
|
||||
session.start(socket, socket);
|
||||
}).listen(port);
|
||||
} else {
|
||||
|
||||
// start a session
|
||||
const session = new MockDebugSession(fsAccessor);
|
||||
process.on('SIGTERM', () => {
|
||||
session.shutdown();
|
||||
});
|
||||
session.start(process.stdin, process.stdout);
|
||||
}
|
||||
|
|
137
src/extension.ts
137
src/extension.ts
|
@ -10,8 +10,9 @@ import { randomBytes } from 'crypto';
|
|||
import { tmpdir } from 'os';
|
||||
import { join } from 'path';
|
||||
import { platform } from 'process';
|
||||
import { WorkspaceFolder, DebugConfiguration, ProviderResult, CancellationToken } from 'vscode';
|
||||
import { ProviderResult } from 'vscode';
|
||||
import { MockDebugSession } from './mockDebug';
|
||||
import { activateMockDebug, workspaceFileAccessor } from './activateMockDebug';
|
||||
|
||||
/*
|
||||
* The compile time flag 'runMode' controls how the debug adapter is run.
|
||||
|
@ -21,141 +22,34 @@ const runMode: 'external' | 'server' | 'namedPipeServer' | 'inline' = 'inline';
|
|||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('extension.mock-debug.runEditorContents', (resource: vscode.Uri) => {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
type: 'mock',
|
||||
name: 'Run Editor Contents',
|
||||
request: 'launch',
|
||||
program: resource.fsPath
|
||||
}, {
|
||||
//noDebug: true
|
||||
});
|
||||
}),
|
||||
vscode.commands.registerCommand('extension.mock-debug.debugEditorContents', (resource: vscode.Uri) => {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
type: 'mock',
|
||||
name: 'Debug Editor Contents',
|
||||
request: 'launch',
|
||||
program: resource.fsPath
|
||||
});
|
||||
}),
|
||||
vscode.commands.registerCommand('extension.mock-debug.showAsHex', (variable) => {
|
||||
vscode.window.showInformationMessage(`${variable.container.name}: ${variable.variable.name}`);
|
||||
})
|
||||
);
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('extension.mock-debug.getProgramName', config => {
|
||||
return vscode.window.showInputBox({
|
||||
placeHolder: "Please enter the name of a markdown file in the workspace folder",
|
||||
value: "readme.md"
|
||||
});
|
||||
}));
|
||||
|
||||
// register a configuration provider for 'mock' debug type
|
||||
const provider = new MockConfigurationProvider();
|
||||
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('mock', provider));
|
||||
|
||||
// register a dynamic configuration provider for 'mock' debug type
|
||||
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('mock', {
|
||||
provideDebugConfigurations(folder: WorkspaceFolder | undefined): ProviderResult<DebugConfiguration[]> {
|
||||
return [
|
||||
{
|
||||
name: "Dynamic Launch",
|
||||
request: "launch",
|
||||
type: "node",
|
||||
program: "${file}"
|
||||
},
|
||||
{
|
||||
name: "Another Dynamic Launch",
|
||||
request: "launch",
|
||||
type: "node",
|
||||
program: "${file}"
|
||||
},
|
||||
{
|
||||
name: "Mock Launch",
|
||||
request: "launch",
|
||||
type: "node",
|
||||
program: "${file}"
|
||||
}
|
||||
];
|
||||
}
|
||||
}, vscode.DebugConfigurationProviderTriggerKind.Dynamic));
|
||||
|
||||
// debug adapters can be run in different ways by using a vscode.DebugAdapterDescriptorFactory:
|
||||
let factory: vscode.DebugAdapterDescriptorFactory;
|
||||
switch (runMode) {
|
||||
case 'server':
|
||||
// run the debug adapter as a server inside the extension and communicate via a socket
|
||||
factory = new MockDebugAdapterServerDescriptorFactory();
|
||||
activateMockDebug(context, new MockDebugAdapterServerDescriptorFactory());
|
||||
break;
|
||||
|
||||
case 'namedPipeServer':
|
||||
// run the debug adapter as a server inside the extension and communicate via a named pipe (Windows) or UNIX domain socket (non-Windows)
|
||||
factory = new MockDebugAdapterNamedPipeServerDescriptorFactory();
|
||||
break;
|
||||
|
||||
case 'inline':
|
||||
// run the debug adapter inside the extension and directly talk to it
|
||||
factory = new InlineDebugAdapterFactory();
|
||||
activateMockDebug(context, new MockDebugAdapterNamedPipeServerDescriptorFactory());
|
||||
break;
|
||||
|
||||
case 'external': default:
|
||||
// run the debug adapter as a separate process
|
||||
factory = new DebugAdapterExecutableFactory();
|
||||
activateMockDebug(context, new DebugAdapterExecutableFactory());
|
||||
break;
|
||||
|
||||
case 'inline':
|
||||
// run the debug adapter inside the extension and directly talk to it
|
||||
activateMockDebug(context);
|
||||
break;
|
||||
}
|
||||
|
||||
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('mock', factory));
|
||||
if ('dispose' in factory) {
|
||||
context.subscriptions.push(factory);
|
||||
}
|
||||
|
||||
// override VS Code's default implementation of the debug hover
|
||||
/*
|
||||
vscode.languages.registerEvaluatableExpressionProvider('markdown', {
|
||||
provideEvaluatableExpression(document: vscode.TextDocument, position: vscode.Position): vscode.ProviderResult<vscode.EvaluatableExpression> {
|
||||
const wordRange = document.getWordRangeAtPosition(position);
|
||||
return wordRange ? new vscode.EvaluatableExpression(wordRange) : undefined;
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
class MockConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
|
||||
/**
|
||||
* Massage a debug configuration just before a debug session is being launched,
|
||||
* e.g. add all missing attributes to the debug configuration.
|
||||
*/
|
||||
resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration> {
|
||||
|
||||
// if launch.json is missing or empty
|
||||
if (!config.type && !config.request && !config.name) {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor && editor.document.languageId === 'markdown') {
|
||||
config.type = 'mock';
|
||||
config.name = 'Launch';
|
||||
config.request = 'launch';
|
||||
config.program = '${file}';
|
||||
config.stopOnEntry = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.program) {
|
||||
return vscode.window.showInformationMessage("Cannot find a program to debug").then(_ => {
|
||||
return undefined; // abort launch
|
||||
});
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescriptorFactory {
|
||||
|
||||
// The following use of a DebugAdapter factory shows how to control what debug adapter executable is used.
|
||||
|
@ -192,7 +86,7 @@ class MockDebugAdapterServerDescriptorFactory implements vscode.DebugAdapterDesc
|
|||
if (!this.server) {
|
||||
// start listening on a random port
|
||||
this.server = Net.createServer(socket => {
|
||||
const session = new MockDebugSession();
|
||||
const session = new MockDebugSession(workspaceFileAccessor);
|
||||
session.setRunAsServer(true);
|
||||
session.start(socket as NodeJS.ReadableStream, socket);
|
||||
}).listen(0);
|
||||
|
@ -221,7 +115,7 @@ class MockDebugAdapterNamedPipeServerDescriptorFactory implements vscode.DebugAd
|
|||
const pipePath = platform === "win32" ? join('\\\\.\\pipe\\', pipeName) : join(tmpdir(), pipeName);
|
||||
|
||||
this.server = Net.createServer(socket => {
|
||||
const session = new MockDebugSession();
|
||||
const session = new MockDebugSession(workspaceFileAccessor);
|
||||
session.setRunAsServer(true);
|
||||
session.start(<NodeJS.ReadableStream>socket, socket);
|
||||
}).listen(pipePath);
|
||||
|
@ -239,10 +133,3 @@ class MockDebugAdapterNamedPipeServerDescriptorFactory implements vscode.DebugAd
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory {
|
||||
|
||||
createDebugAdapterDescriptor(_session: vscode.DebugSession): ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
return new vscode.DebugAdapterInlineImplementation(new MockDebugSession());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from 'vscode-debugadapter';
|
||||
import { DebugProtocol } from 'vscode-debugprotocol';
|
||||
import { basename } from 'path';
|
||||
import { MockRuntime, IMockBreakpoint } from './mockRuntime';
|
||||
import { MockRuntime, IMockBreakpoint, FileAccessor } from './mockRuntime';
|
||||
import { Subject } from 'await-notify';
|
||||
|
||||
function timeout(ms: number) {
|
||||
|
@ -59,14 +59,14 @@ export class MockDebugSession extends LoggingDebugSession {
|
|||
* Creates a new debug adapter that is used for one debug session.
|
||||
* We configure the default implementation of a debug adapter here.
|
||||
*/
|
||||
public constructor() {
|
||||
public constructor(fileAccessor: FileAccessor) {
|
||||
super("mock-debug.txt");
|
||||
|
||||
// this debugger uses zero-based lines and columns
|
||||
this.setDebuggerLinesStartAt1(false);
|
||||
this.setDebuggerColumnsStartAt1(false);
|
||||
|
||||
this._runtime = new MockRuntime();
|
||||
this._runtime = new MockRuntime(fileAccessor);
|
||||
|
||||
// setup event handlers
|
||||
this._runtime.on('stopOnEntry', () => {
|
||||
|
@ -171,12 +171,12 @@ export class MockDebugSession extends LoggingDebugSession {
|
|||
await this._configurationDone.wait(1000);
|
||||
|
||||
// start the program in the runtime
|
||||
this._runtime.start(args.program, !!args.stopOnEntry, !!args.noDebug);
|
||||
await this._runtime.start(args.program, !!args.stopOnEntry, !!args.noDebug);
|
||||
|
||||
this.sendResponse(response);
|
||||
}
|
||||
|
||||
protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void {
|
||||
protected async setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): Promise<void> {
|
||||
|
||||
const path = args.source.path as string;
|
||||
const clientLines = args.lines || [];
|
||||
|
@ -185,12 +185,13 @@ export class MockDebugSession extends LoggingDebugSession {
|
|||
this._runtime.clearBreakpoints(path);
|
||||
|
||||
// set and verify breakpoint locations
|
||||
const actualBreakpoints = clientLines.map(l => {
|
||||
const { verified, line, id } = this._runtime.setBreakPoint(path, this.convertClientLineToDebugger(l));
|
||||
const actualBreakpoints0 = clientLines.map(async l => {
|
||||
const { verified, line, id } = await this._runtime.setBreakPoint(path, this.convertClientLineToDebugger(l));
|
||||
const bp = new Breakpoint(verified, this.convertDebuggerLineToClient(line)) as DebugProtocol.Breakpoint;
|
||||
bp.id= id;
|
||||
return bp;
|
||||
});
|
||||
const actualBreakpoints = await Promise.all<DebugProtocol.Breakpoint>(actualBreakpoints0);
|
||||
|
||||
// send back the actual breakpoint positions
|
||||
response.body = {
|
||||
|
@ -380,7 +381,7 @@ export class MockDebugSession extends LoggingDebugSession {
|
|||
this.sendResponse(response);
|
||||
}
|
||||
|
||||
protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
|
||||
protected async evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): Promise<void> {
|
||||
|
||||
let reply: string | undefined = undefined;
|
||||
|
||||
|
@ -388,7 +389,7 @@ export class MockDebugSession extends LoggingDebugSession {
|
|||
// 'evaluate' supports to create and delete breakpoints from the 'repl':
|
||||
const matches = /new +([0-9]+)/.exec(args.expression);
|
||||
if (matches && matches.length === 2) {
|
||||
const mbp = this._runtime.setBreakPoint(this._runtime.sourceFile, this.convertClientLineToDebugger(parseInt(matches[1])));
|
||||
const mbp = await this._runtime.setBreakPoint(this._runtime.sourceFile, this.convertClientLineToDebugger(parseInt(matches[1])));
|
||||
const bp = new Breakpoint(mbp.verified, this.convertDebuggerLineToClient(mbp.line), undefined, this.createSource(this._runtime.sourceFile)) as DebugProtocol.Breakpoint;
|
||||
bp.id= mbp.id;
|
||||
this.sendEvent(new BreakpointEvent('new', bp));
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
import { readFileSync } from 'fs';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
export interface FileAccessor {
|
||||
readFile(path: string): Promise<string>;
|
||||
}
|
||||
|
||||
export interface IMockBreakpoint {
|
||||
id: number;
|
||||
line: number;
|
||||
|
@ -58,21 +61,21 @@ export class MockRuntime extends EventEmitter {
|
|||
|
||||
private _noDebug = false;
|
||||
|
||||
constructor() {
|
||||
constructor(private _fileAccessor: FileAccessor) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start executing the given program.
|
||||
*/
|
||||
public start(program: string, stopOnEntry: boolean, noDebug: boolean) {
|
||||
public async start(program: string, stopOnEntry: boolean, noDebug: boolean): Promise<void> {
|
||||
|
||||
this._noDebug = noDebug;
|
||||
|
||||
this.loadSource(program);
|
||||
await this.loadSource(program);
|
||||
this._currentLine = -1;
|
||||
|
||||
this.verifyBreakpoints(this._sourceFile);
|
||||
await this.verifyBreakpoints(this._sourceFile);
|
||||
|
||||
if (stopOnEntry) {
|
||||
// we step once
|
||||
|
@ -206,7 +209,7 @@ export class MockRuntime extends EventEmitter {
|
|||
/*
|
||||
* Set breakpoint in file with given line.
|
||||
*/
|
||||
public setBreakPoint(path: string, line: number): IMockBreakpoint {
|
||||
public async setBreakPoint(path: string, line: number): Promise<IMockBreakpoint> {
|
||||
|
||||
const bp: IMockBreakpoint = { verified: false, line, id: this._breakpointId++ };
|
||||
let bps = this._breakPoints.get(path);
|
||||
|
@ -216,7 +219,7 @@ export class MockRuntime extends EventEmitter {
|
|||
}
|
||||
bps.push(bp);
|
||||
|
||||
this.verifyBreakpoints(path);
|
||||
await this.verifyBreakpoints(path);
|
||||
|
||||
return bp;
|
||||
}
|
||||
|
@ -264,10 +267,11 @@ export class MockRuntime extends EventEmitter {
|
|||
|
||||
// private methods
|
||||
|
||||
private loadSource(file: string) {
|
||||
private async loadSource(file: string): Promise<void> {
|
||||
if (this._sourceFile !== file) {
|
||||
this._sourceFile = file;
|
||||
this._sourceLines = readFileSync(this._sourceFile).toString().split('\n');
|
||||
const contents = await this._fileAccessor.readFile(file);
|
||||
this._sourceLines = contents.split('\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,7 +305,7 @@ export class MockRuntime extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
private verifyBreakpoints(path: string): void {
|
||||
private async verifyBreakpoints(path: string): Promise<void> {
|
||||
|
||||
if (this._noDebug) {
|
||||
return;
|
||||
|
@ -309,7 +313,7 @@ export class MockRuntime extends EventEmitter {
|
|||
|
||||
const bps = this._breakPoints.get(path);
|
||||
if (bps) {
|
||||
this.loadSource(path);
|
||||
await this.loadSource(path);
|
||||
bps.forEach(bp => {
|
||||
if (!bp.verified && bp.line < this._sourceLines.length) {
|
||||
const srcLine = this._sourceLines[bp.line].trim();
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/*---------------------------------------------------------
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { activateMockDebug } from '../activateMockDebug';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
activateMockDebug(context);
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
// nothing to do
|
||||
}
|
2257
yarn.lock
2257
yarn.lock
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче