From 11d3b86cff7dc49e1670db93b60555fa3f96be43 Mon Sep 17 00:00:00 2001 From: ewoudje <7384674+ewoudje@users.noreply.github.com> Date: Sun, 24 Sep 2023 20:02:54 +0200 Subject: [PATCH] Lsp update (#266) * Fixed .vscodeignore * You can launch applications with vcode's debugger, not actuall debugging do. * Fixed small configuration typos --- dev/vscode-ext/.vscodeignore | 8 +-- dev/vscode-ext/package.json | 109 ++++++++++++++++++++++------- dev/vscode-ext/src/commands.ts | 43 ++++++++++++ dev/vscode-ext/src/dap.ts | 4 -- dev/vscode-ext/src/extension.ts | 11 ++- dev/vscode-ext/src/lobsterDebug.ts | 43 ++++++++++-- dev/vscode-ext/src/task.ts | 62 ---------------- 7 files changed, 170 insertions(+), 110 deletions(-) create mode 100644 dev/vscode-ext/src/commands.ts delete mode 100644 dev/vscode-ext/src/task.ts diff --git a/dev/vscode-ext/.vscodeignore b/dev/vscode-ext/.vscodeignore index baa6fbac6..1cb7ee273 100644 --- a/dev/vscode-ext/.vscodeignore +++ b/dev/vscode-ext/.vscodeignore @@ -7,10 +7,4 @@ out contributing.md .travis.yml -node_modules/** -!node_modules/vscode-jsonrpc/** -!node_modules/vscode-languageclient/** -!node_modules/vscode-languageserver-protocol/** -!node_modules/vscode-languageserver-types/** -!node_modules/{minimatch,brace-expansion,concat-map,balanced-match}/** -!node_modules/{semver,lru-cache,yallist}/** \ No newline at end of file +node_modules/** \ No newline at end of file diff --git a/dev/vscode-ext/package.json b/dev/vscode-ext/package.json index 922add6e3..955c2b49d 100644 --- a/dev/vscode-ext/package.json +++ b/dev/vscode-ext/package.json @@ -18,9 +18,53 @@ "keywords": [ "lobster" ], - "activationEvents": [], + "activationEvents": [ + "onDebugResolve:lobster", + "onDebugDynamicConfigurations:lobster", + "onCommand:extension.lobster.getProgramName" + ], "main": "./webpack-out/lobster_ext.js", "contributes": { + "menus": { + "editor/title/run": [ + { + "command": "extension.lobster.runEditorContents", + "when": "resourceLangId == lobster", + "group": "navigation@1" + }, + { + "command": "extension.lobster.debugEditorContents", + "when": "resourceLangId == lobster", + "group": "navigation@2" + } + ], + "commandPalette": [ + { + "command": "extension.lobster.debugEditorContents", + "when": "resourceLangId == lobster" + }, + { + "command": "extension.lobster.runEditorContents", + "when": "resourceLangId == lobster" + } + ] + }, + "commands": [ + { + "command": "extension.lobster.debugEditorContents", + "title": "Debug File", + "category": "Lobster", + "enablement": "!inDebugMode", + "icon": "$(debug-alt)" + }, + { + "command": "extension.lobster.runEditorContents", + "title": "Run File", + "category": "Lobster", + "enablement": "!inDebugMode", + "icon": "$(play)" + } + ], "configuration": { "type": "object", "title": "Lobster", @@ -69,28 +113,6 @@ "path": "./syntaxes/lobster.tmLanguage.json" } ], - "taskDefinitions": [ - { - "type": "lobster", - "required": [ - "main" - ], - "properties": { - "main": { - "type": "string", - "description": "The file to run" - }, - "lobsterArgs": { - "type": "array", - "description": "The arguments to pass to lobster" - }, - "programArgs": { - "type": "array", - "description": "The arguments to pass to the program" - } - } - } - ], "breakpoints": [ { "language": "lobster" @@ -111,14 +133,49 @@ "properties": { "program": { "type": "string", - "description": "Path the lobster program to debug", - "default": "${workspaceFolder}/main.lobster" + "description": "Absolute path to a text file.", + "default": "${workspaceFolder}/${command:AskForProgramName}" + }, + "params": { + "type": "array", + "description": "Lobster parameters", + "default": "${workspaceFolder}/${command:AskForProgramName}" + }, + "stopOnEntry": { + "type": "boolean", + "description": "Automatically stop after launch.", + "default": true } } } } } - ] + ], + "initialConfigurations": [ + { + "type": "lobster", + "request": "launch", + "name": "Ask for file name", + "program": "${workspaceFolder}/${command:AskForProgramName}", + "stopOnEntry": true + } + ], + "configurationSnippets": [ + { + "label": "Lobster: Launch", + "description": "A new configuration for 'debugging' a user selected markdown file.", + "body": { + "type": "lobster", + "request": "launch", + "name": "Ask for file name", + "program": "^\"\\${workspaceFolder}/\\${command:AskForProgramName}\"", + "stopOnEntry": true + } + } + ], + "variables": { + "AskForProgramName": "extension.lobster.getProgramName" + } }, "scripts": { "vscode:prepublish": "npm run webpack && shx cp ../lsp/webpack-out/* ./webpack-out/ && npm run icons", diff --git a/dev/vscode-ext/src/commands.ts b/dev/vscode-ext/src/commands.ts new file mode 100644 index 000000000..e0252ea50 --- /dev/null +++ b/dev/vscode-ext/src/commands.ts @@ -0,0 +1,43 @@ +import * as vscode from 'vscode'; + +export function registerCommands(context: vscode.ExtensionContext) { + context.subscriptions.push( + vscode.commands.registerCommand('extension.lobster.runEditorContents', (resource: vscode.Uri) => { + let targetResource = resource; + if (!targetResource && vscode.window.activeTextEditor) { + targetResource = vscode.window.activeTextEditor.document.uri; + } + if (targetResource) { + vscode.debug.startDebugging(undefined, { + type: 'lobster', + name: 'Run File', + request: 'launch', + program: targetResource.fsPath + }, + { noDebug: true } + ); + } + }), + vscode.commands.registerCommand('extension.lobster.debugEditorContents', (resource: vscode.Uri) => { + let targetResource = resource; + if (!targetResource && vscode.window.activeTextEditor) { + targetResource = vscode.window.activeTextEditor.document.uri; + } + if (targetResource) { + vscode.debug.startDebugging(undefined, { + type: 'lobster', + name: 'Run File', + request: 'launch', + program: targetResource.fsPath, + stopOnEntry: true + }); + } + }), + vscode.commands.registerCommand('extension.lobster.getProgramName', config => { + return vscode.window.showInputBox({ + placeHolder: "Please enter the name of a markdown file in the workspace folder", + value: "someFile.lobster" + }); + }) + ); +} \ No newline at end of file diff --git a/dev/vscode-ext/src/dap.ts b/dev/vscode-ext/src/dap.ts index 536a19a20..51efa9047 100644 --- a/dev/vscode-ext/src/dap.ts +++ b/dev/vscode-ext/src/dap.ts @@ -11,14 +11,10 @@ import { import { LobsterDebugSession } from './lobsterDebug'; export class InlineLobsterDebugAdapterFactory implements DebugAdapterDescriptorFactory { - - constructor(readonly module: string) {} - createDebugAdapterDescriptor( session: DebugSession, executable: DebugAdapterExecutable ): ProviderResult { return new DebugAdapterInlineImplementation(new LobsterDebugSession()); } - } \ No newline at end of file diff --git a/dev/vscode-ext/src/extension.ts b/dev/vscode-ext/src/extension.ts index dbd165d6b..06b6cc667 100644 --- a/dev/vscode-ext/src/extension.ts +++ b/dev/vscode-ext/src/extension.ts @@ -8,7 +8,7 @@ import { ServerOptions, TransportKind } from 'vscode-languageclient/node'; -import { registerTasks } from './task'; +import { registerCommands } from './commands'; import { InlineLobsterDebugAdapterFactory } from './dap'; let client: LanguageClient; @@ -50,7 +50,7 @@ export function activate(context: ExtensionContext) { context.subscriptions.push(debug.registerDebugAdapterDescriptorFactory( 'lobster', - new InlineLobsterDebugAdapterFactory("TODO") + new InlineLobsterDebugAdapterFactory() )); context.subscriptions.push(debug.registerDebugConfigurationProvider('lobster', { @@ -72,8 +72,7 @@ export function activate(context: ExtensionContext) { } if (!config.program) { - return window.showInformationMessage("Cannot find a program to debug") - .then(_ => { + return window.showInformationMessage("Cannot find a program to debug").then(_ => { return undefined; // abort launch }); } @@ -93,9 +92,9 @@ export function activate(context: ExtensionContext) { } ]; } - }, DebugConfigurationProviderTriggerKind.Dynamic)); + })); - registerTasks(context); + registerCommands(context); } export function deactivate(): Thenable | undefined { diff --git a/dev/vscode-ext/src/lobsterDebug.ts b/dev/vscode-ext/src/lobsterDebug.ts index 4b809cea9..bf9bf864c 100644 --- a/dev/vscode-ext/src/lobsterDebug.ts +++ b/dev/vscode-ext/src/lobsterDebug.ts @@ -1,16 +1,49 @@ import { - DebugSession + DebugSession, TerminatedEvent } from '@vscode/debugadapter'; import { DebugProtocol } from '@vscode/debugprotocol'; +import { spawn, ChildProcess } from 'child_process'; +import { workspace } from 'vscode'; + +interface ILaunchRequestArguments extends DebugProtocol.LaunchRequestArguments { + /** An absolute path to the "program" to debug. */ + program: string; + + params?: string[]; + /** Automatically stop target after launch. If not specified, target does not stop. */ + stopOnEntry?: boolean; + /** run without debugging */ + noDebug?: boolean; +} -//TODO this should be moved outside vscode extension. export class LobsterDebugSession extends DebugSession { + process: ChildProcess; + protected launchRequest( response: DebugProtocol.LaunchResponse, - args: DebugProtocol.LaunchRequestArguments, - request?: DebugProtocol.Request + args: ILaunchRequestArguments, ): void { - console.log("Whoa"); + //TODO add actual debugging + const executable = workspace.getConfiguration('lobster').get('executable') as string; + const imports = workspace.getConfiguration('lobster').get('imports') as string[]; + + this.process = spawn(executable, [ + ...imports.map(i => "--import " + i), + args.program, + ...(args.params || []) + ]); + + this.process.on('spawn', () => { + this.sendResponse(response); + }); + + this.process.on('error', (err) => { + this.sendErrorResponse(response, 1, "Error executing lobster: {message}", { message: err.message }); + }); + + this.process.on('exit', (code, signal) => { + this.sendEvent(new TerminatedEvent()); + }); } } \ No newline at end of file diff --git a/dev/vscode-ext/src/task.ts b/dev/vscode-ext/src/task.ts deleted file mode 100644 index 1c7b4460f..000000000 --- a/dev/vscode-ext/src/task.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { WorkspaceFolder } from 'vscode'; -import { - ExtensionContext, - ShellExecution, - Task, - TaskDefinition, - TaskScope, - tasks, - workspace, - window -} from 'vscode'; - -interface LobsterRunTaskDefinition extends TaskDefinition { - main: string; - lobsterArgs?: string[]; - programArgs?: string[]; -} - -export function registerTasks(context: ExtensionContext) { - tasks.registerTaskProvider('lobster', { - provideTasks: () => { - return [makeTask( - 'Run current file', - { - type: 'lobster', - main: window.activeTextEditor.document.uri.fsPath - }, - TaskScope.Workspace)]; - }, - resolveTask(task: Task): Task | undefined { - const definition: LobsterRunTaskDefinition = task.definition; - - return makeTask( - task.name, - definition, - task.scope || TaskScope.Workspace - ); - } - }); -} - -function makeTask( - name: string, - definition: LobsterRunTaskDefinition, - scope: TaskScope | WorkspaceFolder -): Task { - const config = workspace.getConfiguration('lobster', null); - const executable = config.get('executable'); - const imports = config.get('imports'); - - return new Task( - definition, - scope, - name, - 'lobster', - new ShellExecution(`${executable} ${imports?.map(i => "--import " + i).join(" ")}` + - (definition.lobsterArgs?.join(' ') || '') + - " " + definition.main + - " -- " + (definition.programArgs?.join(' ') || '') - ) - ); -} \ No newline at end of file