Skip to content

Commit 8e32a96

Browse files
committed
feat(vscode): initial VS Code extension scaffolding to run ubon and surface diagnostics
1 parent 89c6a74 commit 8e32a96

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

vscode-extension/package.json

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"name": "ubon-vscode",
3+
"displayName": "Ubon Security & A11Y Scanner",
4+
"description": "Run Ubon in VS Code and see diagnostics in the Problems panel.",
5+
"version": "0.0.1",
6+
"publisher": "luisfer",
7+
"engines": {
8+
"vscode": "^1.85.0"
9+
},
10+
"categories": ["Linters"],
11+
"activationEvents": [
12+
"onStartupFinished",
13+
"onCommand:ubon.scan"
14+
],
15+
"main": "./dist/extension.js",
16+
"contributes": {
17+
"commands": [
18+
{
19+
"command": "ubon.scan",
20+
"title": "Ubon: Scan Workspace"
21+
}
22+
],
23+
"configuration": {
24+
"type": "object",
25+
"title": "Ubon",
26+
"properties": {
27+
"ubon.cliPath": {
28+
"type": "string",
29+
"default": "ubon",
30+
"description": "Path to the ubon CLI (e.g. 'ubon' if installed globally or an absolute path)."
31+
},
32+
"ubon.args": {
33+
"type": "array",
34+
"default": ["check", "--json"],
35+
"items": { "type": "string" },
36+
"description": "Additional arguments passed to the ubon CLI."
37+
}
38+
}
39+
}
40+
},
41+
"scripts": {
42+
"vscode:prepublish": "npm run build",
43+
"build": "tsc -p ./",
44+
"watch": "tsc -w -p ./"
45+
},
46+
"devDependencies": {
47+
"@types/node": "^18.19.0",
48+
"@types/vscode": "^1.85.0",
49+
"typescript": "^5.4.0"
50+
},
51+
"license": "MIT"
52+
}
53+

vscode-extension/src/extension.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import * as vscode from 'vscode';
2+
import { execFile } from 'child_process';
3+
4+
export function activate(context: vscode.ExtensionContext) {
5+
const diagCollection = vscode.languages.createDiagnosticCollection('ubon');
6+
context.subscriptions.push(diagCollection);
7+
8+
const runScan = () => {
9+
const cliPath = vscode.workspace.getConfiguration().get<string>('ubon.cliPath', 'ubon');
10+
const args = vscode.workspace.getConfiguration().get<string[]>('ubon.args', ['check', '--json']);
11+
const cwd = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || process.cwd();
12+
13+
execFile(cliPath, args, { cwd, maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => {
14+
if (err && !stdout) {
15+
vscode.window.showErrorMessage(`Ubon failed: ${err.message}`);
16+
return;
17+
}
18+
try {
19+
const payload = JSON.parse(stdout || '{}');
20+
const issues = Array.isArray(payload.issues) ? payload.issues : [];
21+
diagCollection.clear();
22+
const byFile = new Map<string, vscode.Diagnostic[]>();
23+
for (const i of issues) {
24+
if (!i.file) continue;
25+
const range = new vscode.Range(
26+
new vscode.Position(Math.max(0, (i.line || i.range?.startLine || 1) - 1), 0),
27+
new vscode.Position(Math.max(0, (i.line || i.range?.endLine || 1) - 1), 1000)
28+
);
29+
const severity = i.type === 'error' ? vscode.DiagnosticSeverity.Error : i.type === 'warning' ? vscode.DiagnosticSeverity.Warning : vscode.DiagnosticSeverity.Information;
30+
const d = new vscode.Diagnostic(range, `${i.ruleId}: ${i.message}`, severity);
31+
d.code = i.ruleId;
32+
const list = byFile.get(i.file) || [];
33+
list.push(d);
34+
byFile.set(i.file, list);
35+
}
36+
for (const [file, diags] of byFile.entries()) {
37+
const uri = vscode.Uri.file(`${cwd}/${file}`);
38+
diagCollection.set(uri, diags);
39+
}
40+
} catch (e: any) {
41+
vscode.window.showErrorMessage(`Ubon parse error: ${e?.message || e}`);
42+
}
43+
});
44+
};
45+
46+
const disposable = vscode.commands.registerCommand('ubon.scan', runScan);
47+
context.subscriptions.push(disposable);
48+
49+
// Optionally run on startup
50+
setTimeout(runScan, 1500);
51+
}
52+
53+
export function deactivate() {}
54+
55+

vscode-extension/tsconfig.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"module": "commonjs",
5+
"lib": ["ES2020"],
6+
"outDir": "dist",
7+
"rootDir": "src",
8+
"strict": true,
9+
"esModuleInterop": true,
10+
"skipLibCheck": true
11+
},
12+
"include": ["src/**/*"]
13+
}
14+

0 commit comments

Comments
 (0)