|  | 
| 1 | 1 | import * as path from 'path'; | 
| 2 | 2 | import { promises as fs } from 'fs'; | 
| 3 |  | -import { spawnSync } from 'child_process'; | 
|  | 3 | +import { spawn } from 'child_process'; | 
| 4 | 4 | import deepEqual from 'deep-equal'; | 
| 5 | 5 | import WebRequest from 'web-request'; | 
| 6 | 6 | import deepmerge from 'deepmerge'; | 
| @@ -108,37 +108,45 @@ export function activate(context: ExtensionContext) { | 
| 108 | 108 |     ); | 
| 109 | 109 | } | 
| 110 | 110 | 
 | 
|  | 111 | +async function exec(command: string, args: string[]): Promise<{ stdout: string, stderr: string }> { | 
|  | 112 | +    return new Promise<{ stdout: string, stderr: string }>((resolve, reject) => { | 
|  | 113 | +        let out = ''; | 
|  | 114 | +        let err = ''; | 
|  | 115 | +        const cp = spawn(command, args); | 
|  | 116 | +        cp.stdout.on('data', data => out += data.toString()); | 
|  | 117 | +        cp.stderr.on('data', data => err += data.toString()); | 
|  | 118 | +        cp.on('error', reject); | 
|  | 119 | +        cp.on('close', (code, signal) => { | 
|  | 120 | +            const stdout = out.trim(); | 
|  | 121 | +            const stderr = err.trim(); | 
|  | 122 | +            if (code) { | 
|  | 123 | +                reject(new Error(stderr ?? `Exit code: ${code}`)); | 
|  | 124 | +            } | 
|  | 125 | +            if (signal) { | 
|  | 126 | +                reject(new Error(stderr ?? `Exit signal: ${signal}`)); | 
|  | 127 | +            } | 
|  | 128 | +            if (err.trim()) { | 
|  | 129 | +                reject(new Error(stderr)); | 
|  | 130 | +            } | 
|  | 131 | +            resolve({ stdout, stderr }); | 
|  | 132 | +        }); | 
|  | 133 | +    }); | 
|  | 134 | +} | 
|  | 135 | + | 
| 111 | 136 | async function startDebug(_: ExtensionContext, config: DebugConfig): Promise<boolean> { | 
| 112 | 137 |     let info: DebugInfo | undefined = undefined; | 
| 113 |  | -    let rawStdout: string | undefined = undefined; | 
| 114 |  | -    let rawStdErr: string | undefined = undefined; | 
| 115 | 138 |     try { | 
| 116 | 139 |         const args = ['debug', '-I', '-b', config.board.fqbn, config.sketchPath, '--format', 'json']; | 
| 117 |  | -        const { stdout, stderr } = spawnSync(config?.cliPath || '.', args, { encoding: 'utf8' }); | 
| 118 |  | -        rawStdout = stdout.trim(); | 
| 119 |  | -        rawStdErr = stderr.trim(); | 
| 120 |  | -    } catch (err) { | 
| 121 |  | -        showError(err); | 
| 122 |  | -        return false; | 
| 123 |  | -    } | 
| 124 |  | -    if (!rawStdout) { | 
| 125 |  | -        if (rawStdErr) { | 
| 126 |  | -            if (rawStdErr.toLowerCase().indexOf('compiled sketch not found in') !== -1) { | 
| 127 |  | -                vscode.window.showErrorMessage(`Sketch '${path.basename(config.sketchPath)}' was not compiled. Please compile the sketch and start debugging again.`); | 
| 128 |  | -            } else { | 
| 129 |  | -                vscode.window.showErrorMessage(rawStdErr); | 
| 130 |  | -            } | 
|  | 140 | +        const { stdout, stderr } = await exec(config?.cliPath || '.', args); | 
|  | 141 | +        if (!stdout && stderr) { | 
|  | 142 | +            throw new Error(stderr); | 
|  | 143 | +        } | 
|  | 144 | +        info = JSON.parse(stdout); | 
|  | 145 | +        if (!info) { | 
|  | 146 | +            return false; | 
| 131 | 147 |         } | 
| 132 |  | -        return false; | 
| 133 |  | -    } | 
| 134 |  | -    try { | 
| 135 |  | -        info = JSON.parse(rawStdout); | 
| 136 | 148 |     } catch (err) { | 
| 137 |  | -        console.error(`Could not parse JSON: <${rawStdout}>`); | 
| 138 |  | -        showError(err); | 
| 139 |  | -    } | 
| 140 |  | -    if (!info) { | 
| 141 |  | -        return false; | 
|  | 149 | +        throw err; | 
| 142 | 150 |     } | 
| 143 | 151 |     const defaultDebugConfig = { | 
| 144 | 152 |         cwd: '${workspaceRoot}', | 
| @@ -270,12 +278,6 @@ async function buildLanguageClient(config: LanguageServerConfig): Promise<Langua | 
| 270 | 278 |     ); | 
| 271 | 279 | } | 
| 272 | 280 | 
 | 
| 273 |  | -function showError(err: unknown): void { | 
| 274 |  | -    console.error(err); | 
| 275 |  | -    const message = err instanceof Error ? err.message : typeof err === 'string' ? err : String(err); | 
| 276 |  | -    vscode.window.showErrorMessage(message); | 
| 277 |  | -} | 
| 278 |  | - | 
| 279 | 281 | /** | 
| 280 | 282 |  * Instead of writing the `launch.json` to the workspace, the file is written to the temporary binary output location. | 
| 281 | 283 |  */ | 
|  | 
0 commit comments