Skip to content

Commit

Permalink
Mutex lock for asynchronous shell execution (#145)
Browse files Browse the repository at this point in the history
* Closes #141
  • Loading branch information
lukaszcz authored Sep 5, 2024
1 parent 4918627 commit 626e739
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 55 deletions.
10 changes: 7 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
{
"version": "0.2.0",
"version": "0.2.4",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
},
{
Expand Down
15 changes: 12 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "juvix-mode",
"version": "0.2.3",
"version": "0.2.4",
"license": "GPL-3.0",
"description": "Juvix Mode for VSCode",
"displayName": "Juvix",
Expand Down Expand Up @@ -857,14 +857,15 @@
}
},
"dependencies": {
"@vscode/vsce": "^2.15.0",
"async-mutex": "^0.5.0",
"compare-versions": "^6.1.0",
"eslint": "^8.57.0",
"globals": "^15.8.0",
"mobx": "^6.13.0",
"run": "^1.5.0",
"temp": "^0.9.4",
"typescript": "^5.5.3",
"@vscode/vsce": "^2.15.0"
"typescript": "^5.5.3"
},
"devDependencies": {
"@eslint/js": "^8.57.0",
Expand Down
103 changes: 57 additions & 46 deletions src/utils/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*--------------------------------------------------------*/
import { spawn, spawnSync } from 'child_process';
import * as vscode from 'vscode';
import { Mutex } from 'async-mutex';

export function needsJuvix(document: vscode.TextDocument): boolean {
return (
Expand Down Expand Up @@ -40,59 +41,69 @@ export function runShellCommandSync(command: string, input?: string): { stdout:
return spawnSync(command, { shell: true, input, encoding: 'utf8' });
}

const shellLock = new Mutex();

export async function runShellCommand(command: string, input?: string): Promise<{ stdout: string, stderr: string, status: number | null }> {
const release = await shellLock.acquire();
return new Promise((resolve, reject) => {
const child = spawn(command, { shell: true });

let stdout = '';
let stderr = '';

if (input !== undefined) {
child.stdin.setDefaultEncoding('utf8');
child.stdin.write(input);
child.stdin.end();
}

child.stdout.on('data', (data) => {
stdout += data.toString();
});

child.stderr.on('data', (data) => {
stderr += data.toString();
});

child.on('close', (status) => {
resolve({ stdout, stderr, status });
});

child.on('error', (err) => {
try {
const child = spawn(command, { shell: true });

let stdout = '';
let stderr = '';

if (input !== undefined) {
child.stdin.setDefaultEncoding('utf8');
child.stdin.write(input);
child.stdin.end();
}

child.stdout.on('data', (data) => {
stdout += data.toString();
});

child.stderr.on('data', (data) => {
stderr += data.toString();
});

child.on('close', (status) => {
release();
resolve({ stdout, stderr, status });
});

child.on('error', (err) => {
release();
reject(err);
});
} catch (err) {
release();
reject(err);
});
}
});
}

const regexJuvixError = /(?<file>.*):(?<line>\d+):(?<begin_col>\d+)-?(?<end_col>\d+)?:\s(?<err_type>.*):\s?(?<msg>((\n|.)*))/g;

export function getDiagnosticFromError(output: string): vscode.Diagnostic | undefined {
const { file, line, begin_col, end_col, err_type, msg } = regexJuvixError.exec(output)!.groups!;
if (!msg || !line || !begin_col) return undefined;
const range = new vscode.Range(
new vscode.Position(parseInt(line) - 1 , parseInt(begin_col) - 1 ),
new vscode.Position(parseInt(line) - 1 , parseInt(end_col ?? begin_col) - 1 ),
);
let severity;
switch (err_type) {
case 'error':
severity = vscode.DiagnosticSeverity.Error;
break;
case 'warning':
severity = vscode.DiagnosticSeverity.Warning;
break;
case 'info':
severity = vscode.DiagnosticSeverity.Information;
break;
}
let diag = new vscode.Diagnostic(range, msg, severity);
diag.source = 'Juvix';
return diag;
const { file, line, begin_col, end_col, err_type, msg } = regexJuvixError.exec(output)!.groups!;
if (!msg || !line || !begin_col) return undefined;
const range = new vscode.Range(
new vscode.Position(parseInt(line) - 1, parseInt(begin_col) - 1),
new vscode.Position(parseInt(line) - 1, parseInt(end_col ?? begin_col) - 1),
);
let severity;
switch (err_type) {
case 'error':
severity = vscode.DiagnosticSeverity.Error;
break;
case 'warning':
severity = vscode.DiagnosticSeverity.Warning;
break;
case 'info':
severity = vscode.DiagnosticSeverity.Information;
break;
}
const diag = new vscode.Diagnostic(range, msg, severity);
diag.source = 'Juvix';
return diag;
}

0 comments on commit 626e739

Please sign in to comment.