From d58cd796120e4c2e9f05cf361e6711afde682d12 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 18 Jan 2024 15:29:21 +0100 Subject: [PATCH 1/6] Gracefully handle debugger loading/init errors --- package.json | 3 +- src/extension.ts | 86 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 5108a91..f72833d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ ], "activationEvents": [ "onLanguage:noir", - "onStartupFinished" + "onStartupFinished", + "onDebug" ], "main": "./out/extension", "contributes": { diff --git a/src/extension.ts b/src/extension.ts index c035472..3b64444 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,7 +17,6 @@ */ import { - window, workspace, commands, debug, @@ -45,6 +44,7 @@ import { DebugAdapterExecutable, DebugSession, ProviderResult, + OutputChannel, } from 'vscode'; import { languageId } from './constants'; @@ -53,10 +53,14 @@ import findNargo from './find-nargo'; import findNearestPackageFrom from './find-nearest-package'; import { lspClients, editorLineDecorationManager } from './noir'; +import { spawn } from 'child_process'; + const activeCommands: Map = new Map(); +let outputChannel: OutputChannel; + class NoirDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory { - createDebugAdapterDescriptor( + async createDebugAdapterDescriptor( _session: DebugSession, _executable: DebugAdapterExecutable, ): ProviderResult { @@ -348,6 +352,8 @@ async function didChangeWorkspaceFolders(event: WorkspaceFoldersChangeEvent) { } export async function activate(context: ExtensionContext): Promise { + outputChannel = window.createOutputChannel('NoirDebugger'); + const didOpenTextDocument$ = workspace.onDidOpenTextDocument(didOpenTextDocument); const didChangeWorkspaceFolders$ = workspace.onDidChangeWorkspaceFolders(didChangeWorkspaceFolders); const restart$ = commands.registerCommand('noir.restart', restartAllClients); @@ -361,10 +367,10 @@ export async function activate(context: ExtensionContext): Promise { context.subscriptions.push( debug.registerDebugAdapterDescriptorFactory('noir', new NoirDebugAdapterDescriptorFactory()), - ); - - context.subscriptions.push( debug.registerDebugConfigurationProvider('noir', new NoirDebugConfigurationProvider()), + debug.onDidTerminateDebugSession(() => { + outputChannel.appendLine("Debug session ended."); + }), ); } @@ -374,25 +380,81 @@ export async function deactivate(): Promise { } } +/** + * Takes stderr or stdout output from the Nargo's DAP + * preflight check and formats it in an Output pane friendly way, + * by removing all special characters. + * + * Note: VS Code's output panes only support plain text. + * + */ +function preflightCheckPrinter(buffer: Buffer, output: OutputChannel) { + const formattedOutput = buffer.toString() + .replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '') + .replace(/[^ -~\n\t]/g, ''); + + output.appendLine(formattedOutput); +} + class NoirDebugConfigurationProvider implements DebugConfigurationProvider { - resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult { + async resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult { if (config.program || config.request == 'attach') return config; if (window.activeTextEditor?.document.languageId != 'noir') - return window.showInformationMessage("Select a Noir file to debug").then(_ => { - return null; - }); + return window.showInformationMessage("Select a Noir file to debug"); const currentFilePath = window.activeTextEditor.document.uri.fsPath; - let currentProject = findNearestPackageFrom(currentFilePath); + let currentProjectFolder = findNearestPackageFrom(currentFilePath); + + const workspaceConfig = workspace.getConfiguration('noir'); + const nargoPath = workspaceConfig.get('nargoPath') || findNargo(); + + outputChannel.clear(); + outputChannel.appendLine(`Using nargo at ${nargoPath}`); + outputChannel.appendLine("Compiling Noir project..."); + outputChannel.appendLine(""); + + // Run Nargo's DAP in "pre-flight mode", which test runs + // the DAP initialization code without actually starting the DAP server. + // This lets us gracefully handle errors that happen *before* + // the DAP loop is established, which otherwise are considered + // "out of band". + const preflightCheck = spawn(nargoPath, [ + 'dap', + '--preflight-check', + '--preflight-project-folder', + currentProjectFolder + ]); + + // Create a promise to block until the preflight check child process + // ends. + let ready: (r: Boolean) => void; + const preflightCheckMonitor = new Promise((resolve) => ready = resolve); + + preflightCheck.stderr.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.stdout.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.on('exit', async code => { + if (code !== 0) { + outputChannel.appendLine(`Exited with code ${code}`); + } + ready(code == 0); + }); + + if (!await preflightCheckMonitor) { + outputChannel.show(); + throw new Error("Error launching debugger. Please inspect the Output pane for more details."); + } else { + outputChannel.appendLine("Starting debugger session..."); + } return { type: 'noir', name: 'Noir binary package', request: 'launch', program: currentFilePath, - projectFolder: currentProject, + projectFolder: currentProjectFolder, } } -} +} \ No newline at end of file From 61179adbca26c4808c1b6292e3eaf19ccce13ba1 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Thu, 18 Jan 2024 15:29:48 +0100 Subject: [PATCH 2/6] Refactor: extract debugger functionality to own file --- src/debugger.ts | 126 +++++++++++++++++++++++++++++++++++++++++++++++ src/extension.ts | 122 ++------------------------------------------- 2 files changed, 131 insertions(+), 117 deletions(-) create mode 100644 src/debugger.ts diff --git a/src/debugger.ts b/src/debugger.ts new file mode 100644 index 0000000..89aa1c2 --- /dev/null +++ b/src/debugger.ts @@ -0,0 +1,126 @@ +import { + debug, + window, + workspace, + DebugAdapterDescriptorFactory, + DebugSession, + DebugAdapterExecutable, + DebugAdapterDescriptor, + ExtensionContext, + OutputChannel, + DebugConfigurationProvider, + CancellationToken, + DebugConfiguration, + ProviderResult, +} from 'vscode'; + +import { spawn } from 'child_process'; +import findNargo from './find-nargo'; +import findNearestPackageFrom from './find-nearest-package'; + +let outputChannel: OutputChannel; + +export function activateDebugger(context: ExtensionContext) { + outputChannel = window.createOutputChannel('NoirDebugger'); + + context.subscriptions.push( + debug.registerDebugAdapterDescriptorFactory('noir', new NoirDebugAdapterDescriptorFactory()), + debug.registerDebugConfigurationProvider('noir', new NoirDebugConfigurationProvider()), + debug.onDidTerminateDebugSession(() => { + outputChannel.appendLine("Debug session ended."); + }), + ); +} + +export class NoirDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory { + async createDebugAdapterDescriptor( + _session: DebugSession, + _executable: DebugAdapterExecutable, + ): ProviderResult { + const config = workspace.getConfiguration('noir'); + + const configuredNargoPath = config.get('nargoPath'); + const nargoPath = configuredNargoPath || findNargo(); + + return new DebugAdapterExecutable(nargoPath, ['dap']); + } +} + +class NoirDebugConfigurationProvider implements DebugConfigurationProvider { + async resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult { + if (config.program || config.request == 'attach') + return config; + + if (window.activeTextEditor?.document.languageId != 'noir') + return window.showInformationMessage("Select a Noir file to debug"); + + const currentFilePath = window.activeTextEditor.document.uri.fsPath; + let currentProjectFolder = findNearestPackageFrom(currentFilePath); + + const workspaceConfig = workspace.getConfiguration('noir'); + const nargoPath = workspaceConfig.get('nargoPath') || findNargo(); + + outputChannel.clear(); + outputChannel.appendLine(`Using nargo at ${nargoPath}`); + outputChannel.appendLine("Compiling Noir project..."); + outputChannel.appendLine(""); + + // Run Nargo's DAP in "pre-flight mode", which test runs + // the DAP initialization code without actually starting the DAP server. + // This lets us gracefully handle errors that happen *before* + // the DAP loop is established, which otherwise are considered + // "out of band". + const preflightCheck = spawn(nargoPath, [ + 'dap', + '--preflight-check', + '--preflight-project-folder', + currentProjectFolder + ]); + + // Create a promise to block until the preflight check child process + // ends. + let ready: (r: Boolean) => void; + const preflightCheckMonitor = new Promise((resolve) => ready = resolve); + + preflightCheck.stderr.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.stdout.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.on('exit', async code => { + if (code !== 0) { + outputChannel.appendLine(`Exited with code ${code}`); + } + ready(code == 0); + }); + + if (!await preflightCheckMonitor) { + outputChannel.show(); + throw new Error("Error launching debugger. Please inspect the Output pane for more details."); + } else { + outputChannel.appendLine("Starting debugger session..."); + } + + return { + type: 'noir', + name: 'Noir binary package', + request: 'launch', + program: currentFilePath, + projectFolder: currentProjectFolder, + } + } +} + +/** + * Takes stderr or stdout output from the Nargo's DAP + * preflight check and formats it in an Output pane friendly way, + * by removing all special characters. + * + * Note: VS Code's output panes only support plain text. + * + */ +function preflightCheckPrinter(buffer: Buffer, output: OutputChannel) { + const formattedOutput = buffer.toString() + .replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '') + .replace(/[^ -~\n\t]/g, ''); + + output.appendLine(formattedOutput); +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 3b64444..7fe622b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,9 +17,9 @@ */ import { + window, workspace, commands, - debug, ExtensionContext, Disposable, TextDocument, @@ -34,45 +34,20 @@ import { TaskPanelKind, TaskGroup, ProcessExecution, - window, - ProgressLocation, - DebugAdapterDescriptorFactory, - DebugConfigurationProvider, - CancellationToken, - DebugConfiguration, - DebugAdapterDescriptor, - DebugAdapterExecutable, - DebugSession, - ProviderResult, - OutputChannel, + ProgressLocation, } from 'vscode'; +import { activateDebugger } from './debugger'; + import { languageId } from './constants'; import Client from './client'; import findNargo from './find-nargo'; -import findNearestPackageFrom from './find-nearest-package'; import { lspClients, editorLineDecorationManager } from './noir'; -import { spawn } from 'child_process'; - const activeCommands: Map = new Map(); let outputChannel: OutputChannel; -class NoirDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory { - async createDebugAdapterDescriptor( - _session: DebugSession, - _executable: DebugAdapterExecutable, - ): ProviderResult { - const config = workspace.getConfiguration('noir'); - - const configuredNargoPath = config.get('nargoPath'); - const nargoPath = configuredNargoPath || findNargo(); - - return new DebugAdapterExecutable(nargoPath, ['dap']); - } -} - const activeMutex: Set = new Set(); function mutex(key: string, fn: (...args: unknown[]) => Promise) { @@ -352,8 +327,6 @@ async function didChangeWorkspaceFolders(event: WorkspaceFoldersChangeEvent) { } export async function activate(context: ExtensionContext): Promise { - outputChannel = window.createOutputChannel('NoirDebugger'); - const didOpenTextDocument$ = workspace.onDidOpenTextDocument(didOpenTextDocument); const didChangeWorkspaceFolders$ = workspace.onDidChangeWorkspaceFolders(didChangeWorkspaceFolders); const restart$ = commands.registerCommand('noir.restart', restartAllClients); @@ -365,96 +338,11 @@ export async function activate(context: ExtensionContext): Promise { context.subscriptions.push(disposable); } - context.subscriptions.push( - debug.registerDebugAdapterDescriptorFactory('noir', new NoirDebugAdapterDescriptorFactory()), - debug.registerDebugConfigurationProvider('noir', new NoirDebugConfigurationProvider()), - debug.onDidTerminateDebugSession(() => { - outputChannel.appendLine("Debug session ended."); - }), - ); + activateDebugger(context); } export async function deactivate(): Promise { for (const client of lspClients.values()) { await client.stop(); } -} - -/** - * Takes stderr or stdout output from the Nargo's DAP - * preflight check and formats it in an Output pane friendly way, - * by removing all special characters. - * - * Note: VS Code's output panes only support plain text. - * - */ -function preflightCheckPrinter(buffer: Buffer, output: OutputChannel) { - const formattedOutput = buffer.toString() - .replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '') - .replace(/[^ -~\n\t]/g, ''); - - output.appendLine(formattedOutput); -} - -class NoirDebugConfigurationProvider implements DebugConfigurationProvider { - async resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult { - if (config.program || config.request == 'attach') - return config; - - if (window.activeTextEditor?.document.languageId != 'noir') - return window.showInformationMessage("Select a Noir file to debug"); - - const currentFilePath = window.activeTextEditor.document.uri.fsPath; - let currentProjectFolder = findNearestPackageFrom(currentFilePath); - - const workspaceConfig = workspace.getConfiguration('noir'); - const nargoPath = workspaceConfig.get('nargoPath') || findNargo(); - - outputChannel.clear(); - outputChannel.appendLine(`Using nargo at ${nargoPath}`); - outputChannel.appendLine("Compiling Noir project..."); - outputChannel.appendLine(""); - - // Run Nargo's DAP in "pre-flight mode", which test runs - // the DAP initialization code without actually starting the DAP server. - // This lets us gracefully handle errors that happen *before* - // the DAP loop is established, which otherwise are considered - // "out of band". - const preflightCheck = spawn(nargoPath, [ - 'dap', - '--preflight-check', - '--preflight-project-folder', - currentProjectFolder - ]); - - // Create a promise to block until the preflight check child process - // ends. - let ready: (r: Boolean) => void; - const preflightCheckMonitor = new Promise((resolve) => ready = resolve); - - preflightCheck.stderr.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); - preflightCheck.stdout.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); - preflightCheck.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); - preflightCheck.on('exit', async code => { - if (code !== 0) { - outputChannel.appendLine(`Exited with code ${code}`); - } - ready(code == 0); - }); - - if (!await preflightCheckMonitor) { - outputChannel.show(); - throw new Error("Error launching debugger. Please inspect the Output pane for more details."); - } else { - outputChannel.appendLine("Starting debugger session..."); - } - - return { - type: 'noir', - name: 'Noir binary package', - request: 'launch', - program: currentFilePath, - projectFolder: currentProjectFolder, - } - } } \ No newline at end of file From 49f0de89fc37c240e16acf74ba74a3187b39fe19 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Fri, 19 Jan 2024 12:08:13 +0100 Subject: [PATCH 3/6] Fix lint errors --- src/debugger.ts | 51 ++++++++++++++++++++----------------- src/extension.ts | 6 ++--- src/find-nearest-package.ts | 45 +++++++++++++++----------------- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/debugger.ts b/src/debugger.ts index 89aa1c2..80c91ab 100644 --- a/src/debugger.ts +++ b/src/debugger.ts @@ -27,7 +27,7 @@ export function activateDebugger(context: ExtensionContext) { debug.registerDebugAdapterDescriptorFactory('noir', new NoirDebugAdapterDescriptorFactory()), debug.registerDebugConfigurationProvider('noir', new NoirDebugConfigurationProvider()), debug.onDidTerminateDebugSession(() => { - outputChannel.appendLine("Debug session ended."); + outputChannel.appendLine(`Debug session ended.`); }), ); } @@ -47,23 +47,26 @@ export class NoirDebugAdapterDescriptorFactory implements DebugAdapterDescriptor } class NoirDebugConfigurationProvider implements DebugConfigurationProvider { - async resolveDebugConfiguration(folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult { - if (config.program || config.request == 'attach') - return config; + async resolveDebugConfiguration( + folder: WorkspaceFolder | undefined, + config: DebugConfiguration, + _token?: CancellationToken, + ): ProviderResult { + if (config.program || config.request == 'attach') return config; if (window.activeTextEditor?.document.languageId != 'noir') - return window.showInformationMessage("Select a Noir file to debug"); + return window.showInformationMessage(`Select a Noir file to debug`); const currentFilePath = window.activeTextEditor.document.uri.fsPath; - let currentProjectFolder = findNearestPackageFrom(currentFilePath); + const currentProjectFolder = findNearestPackageFrom(currentFilePath); const workspaceConfig = workspace.getConfiguration('noir'); const nargoPath = workspaceConfig.get('nargoPath') || findNargo(); outputChannel.clear(); outputChannel.appendLine(`Using nargo at ${nargoPath}`); - outputChannel.appendLine("Compiling Noir project..."); - outputChannel.appendLine(""); + outputChannel.appendLine(`Compiling Noir project...`); + outputChannel.appendLine(``); // Run Nargo's DAP in "pre-flight mode", which test runs // the DAP initialization code without actually starting the DAP server. @@ -74,29 +77,29 @@ class NoirDebugConfigurationProvider implements DebugConfigurationProvider { 'dap', '--preflight-check', '--preflight-project-folder', - currentProjectFolder + currentProjectFolder, ]); // Create a promise to block until the preflight check child process // ends. - let ready: (r: Boolean) => void; - const preflightCheckMonitor = new Promise((resolve) => ready = resolve); + let ready: (r: boolean) => void; + const preflightCheckMonitor = new Promise((resolve) => (ready = resolve)); - preflightCheck.stderr.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); - preflightCheck.stdout.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); - preflightCheck.on('data', ev_buffer => preflightCheckPrinter(ev_buffer, outputChannel)); - preflightCheck.on('exit', async code => { + preflightCheck.stderr.on('data', (ev_buffer) => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.stdout.on('data', (ev_buffer) => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.on('data', (ev_buffer) => preflightCheckPrinter(ev_buffer, outputChannel)); + preflightCheck.on('exit', async (code) => { if (code !== 0) { outputChannel.appendLine(`Exited with code ${code}`); } ready(code == 0); }); - if (!await preflightCheckMonitor) { + if (!(await preflightCheckMonitor)) { outputChannel.show(); - throw new Error("Error launching debugger. Please inspect the Output pane for more details."); + throw new Error(`Error launching debugger. Please inspect the Output pane for more details.`); } else { - outputChannel.appendLine("Starting debugger session..."); + outputChannel.appendLine(`Starting debugger session...`); } return { @@ -105,7 +108,7 @@ class NoirDebugConfigurationProvider implements DebugConfigurationProvider { request: 'launch', program: currentFilePath, projectFolder: currentProjectFolder, - } + }; } } @@ -118,9 +121,11 @@ class NoirDebugConfigurationProvider implements DebugConfigurationProvider { * */ function preflightCheckPrinter(buffer: Buffer, output: OutputChannel) { - const formattedOutput = buffer.toString() - .replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '') - .replace(/[^ -~\n\t]/g, ''); + const formattedOutput = buffer + .toString() + // eslint-disable-next-line no-control-regex + .replace(/\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '') + .replace(/[^ -~\n\t]/g, ''); output.appendLine(formattedOutput); -} \ No newline at end of file +} diff --git a/src/extension.ts b/src/extension.ts index 7fe622b..79c5f72 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -34,7 +34,7 @@ import { TaskPanelKind, TaskGroup, ProcessExecution, - ProgressLocation, + ProgressLocation, } from 'vscode'; import { activateDebugger } from './debugger'; @@ -46,8 +46,6 @@ import { lspClients, editorLineDecorationManager } from './noir'; const activeCommands: Map = new Map(); -let outputChannel: OutputChannel; - const activeMutex: Set = new Set(); function mutex(key: string, fn: (...args: unknown[]) => Promise) { @@ -345,4 +343,4 @@ export async function deactivate(): Promise { for (const client of lspClients.values()) { await client.stop(); } -} \ No newline at end of file +} diff --git a/src/find-nearest-package.ts b/src/find-nearest-package.ts index 05b3774..ce5fba0 100644 --- a/src/find-nearest-package.ts +++ b/src/find-nearest-package.ts @@ -5,37 +5,34 @@ import * as fs from 'fs'; /** * Given a program file path, walk up the file system until * finding the nearest a Nargo.toml in a directory that contains - * the program. - * + * the program. + * * To reduce the odds of accidentally choosing the wrong Nargo package, - * end the walk at the root of the current VS Code open files. + * end the walk at the root of the current VS Code open files. */ export default function findNearestPackageFolder(program: string): string { - const workspaceFolders = vscode.workspace.workspaceFolders; - if (!workspaceFolders) { - throw new Error("No workspace is currently open in VS Code."); - } + const workspaceFolders = vscode.workspace.workspaceFolders; + if (!workspaceFolders) { + throw new Error(`No workspace is currently open in VS Code.`); + } - const workspaceRoots = workspaceFolders.map(wf => wf.uri.fsPath); + const workspaceRoots = workspaceFolders.map((wf) => wf.uri.fsPath); - let currentFolder = path.dirname(program); + let currentFolder = path.dirname(program); - try { - while ( - currentFolder !== path.dirname(currentFolder) && - !workspaceRoots.includes(currentFolder) - ) { - const maybeNargoProject = path.join(currentFolder, 'Nargo.toml'); + try { + while (currentFolder !== path.dirname(currentFolder) && !workspaceRoots.includes(currentFolder)) { + const maybeNargoProject = path.join(currentFolder, 'Nargo.toml'); - if (fs.existsSync(maybeNargoProject)) { - return currentFolder; - } + if (fs.existsSync(maybeNargoProject)) { + return currentFolder; + } - currentFolder = path.dirname(currentFolder); - } - } catch (error) { - throw new Error("Could not find a Nargo package associated to this file."); - } + currentFolder = path.dirname(currentFolder); + } + } catch (error) { + throw new Error(`Could not find a Nargo package associated to this file.`); + } - throw new Error("Could not find a Nargo package associated to this file."); + throw new Error(`Could not find a Nargo package associated to this file.`); } From 85c582a51faf1688be3ca70bade9b9fb6d53dc66 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Fri, 19 Jan 2024 12:15:55 +0100 Subject: [PATCH 4/6] Remove unnecessary line --- src/debugger.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/debugger.ts b/src/debugger.ts index 80c91ab..367a7f5 100644 --- a/src/debugger.ts +++ b/src/debugger.ts @@ -48,12 +48,10 @@ export class NoirDebugAdapterDescriptorFactory implements DebugAdapterDescriptor class NoirDebugConfigurationProvider implements DebugConfigurationProvider { async resolveDebugConfiguration( - folder: WorkspaceFolder | undefined, - config: DebugConfiguration, + _folder: WorkspaceFolder | undefined, + _config: DebugConfiguration, _token?: CancellationToken, ): ProviderResult { - if (config.program || config.request == 'attach') return config; - if (window.activeTextEditor?.document.languageId != 'noir') return window.showInformationMessage(`Select a Noir file to debug`); From 478bac9ac525c42f1db7303857fd3fdb0879d946 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Fri, 19 Jan 2024 13:44:56 +0100 Subject: [PATCH 5/6] Properly handle launch.json if exists --- src/debugger.ts | 55 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/debugger.ts b/src/debugger.ts index 367a7f5..5f9124e 100644 --- a/src/debugger.ts +++ b/src/debugger.ts @@ -49,19 +49,35 @@ export class NoirDebugAdapterDescriptorFactory implements DebugAdapterDescriptor class NoirDebugConfigurationProvider implements DebugConfigurationProvider { async resolveDebugConfiguration( _folder: WorkspaceFolder | undefined, - _config: DebugConfiguration, + config: DebugConfiguration, _token?: CancellationToken, ): ProviderResult { if (window.activeTextEditor?.document.languageId != 'noir') return window.showInformationMessage(`Select a Noir file to debug`); - const currentFilePath = window.activeTextEditor.document.uri.fsPath; - const currentProjectFolder = findNearestPackageFrom(currentFilePath); - const workspaceConfig = workspace.getConfiguration('noir'); const nargoPath = workspaceConfig.get('nargoPath') || findNargo(); + const currentFilePath = window.activeTextEditor.document.uri.fsPath; + const projectFolder = + config.projectFolder && config.projectFolder !== `` + ? config.projectFolder + : findNearestPackageFrom(currentFilePath); + + const resolvedConfig = { + type: config.type || 'noir', + name: config.name || 'Noir binary package', + request: 'launch', + program: currentFilePath, + projectFolder, + package: config.package || ``, + proverName: config.proverName || `Prover`, + generateAcir: config.generateAcir || false, + skipInstrumentation: config.skipInstrumentation || false, + }; + outputChannel.clear(); + outputChannel.appendLine(`Using nargo at ${nargoPath}`); outputChannel.appendLine(`Compiling Noir project...`); outputChannel.appendLine(``); @@ -71,12 +87,29 @@ class NoirDebugConfigurationProvider implements DebugConfigurationProvider { // This lets us gracefully handle errors that happen *before* // the DAP loop is established, which otherwise are considered // "out of band". - const preflightCheck = spawn(nargoPath, [ + const preflightArgs = [ 'dap', '--preflight-check', '--preflight-project-folder', - currentProjectFolder, - ]); + resolvedConfig.projectFolder, + '--preflight-prover-name', + resolvedConfig.proverName, + ]; + + if (resolvedConfig.package !== ``) { + preflightArgs.push(`--preflight-package`); + preflightArgs.push(config.package); + } + + if (resolvedConfig.generateAcir) { + preflightArgs.push(`--preflight-generate-acir`); + } + + if (resolvedConfig.skipInstrumentation) { + preflightArgs.push(`--preflight-skip-instrumentation`); + } + + const preflightCheck = spawn(nargoPath, preflightArgs); // Create a promise to block until the preflight check child process // ends. @@ -100,13 +133,7 @@ class NoirDebugConfigurationProvider implements DebugConfigurationProvider { outputChannel.appendLine(`Starting debugger session...`); } - return { - type: 'noir', - name: 'Noir binary package', - request: 'launch', - program: currentFilePath, - projectFolder: currentProjectFolder, - }; + return resolvedConfig; } } From 3addaaf2f990234d7efa5f5db497983785eee764 Mon Sep 17 00:00:00 2001 From: Martin Verzilli Date: Fri, 19 Jan 2024 13:58:57 +0100 Subject: [PATCH 6/6] Add a bit more context on preflight check --- src/debugger.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/debugger.ts b/src/debugger.ts index 5f9124e..6636ce8 100644 --- a/src/debugger.ts +++ b/src/debugger.ts @@ -87,6 +87,10 @@ class NoirDebugConfigurationProvider implements DebugConfigurationProvider { // This lets us gracefully handle errors that happen *before* // the DAP loop is established, which otherwise are considered // "out of band". + // This was necessary due to the VS Code project being reluctant to let extension authors capture + // stderr output generated by a DAP server wrapped in DebugAdapterExecutable. + // + // More details here: https://github.com/microsoft/vscode/issues/108138 const preflightArgs = [ 'dap', '--preflight-check',