0.2.1, bug fixes and new match new compiler
This commit is contained in:
parent
69a82a563e
commit
8ad44334d8
13
package.json
13
package.json
|
@ -47,7 +47,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"configuration": {
|
||||||
|
"title": "hblang",
|
||||||
|
"properties": {
|
||||||
|
"hblang.compilerPath": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "PATH",
|
||||||
|
"description": "Set the optional path for the hbc compiler. If set to 'PATH', it will rely on the system to provide hbc.",
|
||||||
|
"scope": "machine-overridable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"vscode:prepublish": "webpack",
|
"vscode:prepublish": "webpack",
|
||||||
|
|
184
src/main.ts
184
src/main.ts
|
@ -1,124 +1,120 @@
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from "vscode";
|
||||||
import { execFile } from 'child_process';
|
import { execFile } from "child_process";
|
||||||
import * as fs from 'fs';
|
import * as fs from "fs";
|
||||||
import * as path from 'path';
|
import * as path from "path";
|
||||||
|
|
||||||
vscode.languages.registerDocumentFormattingEditProvider('hblang', {
|
const DEFAULT_EXECUTABLE = "hbc";
|
||||||
async provideDocumentFormattingEdits(document: vscode.TextDocument): Promise<vscode.TextEdit[]> {
|
let diagnosticCollection: vscode.DiagnosticCollection;
|
||||||
const filePath = document.uri.fsPath;
|
|
||||||
const tempFilePath = path.join(path.dirname(filePath), `temp_${path.basename(filePath)}`);
|
|
||||||
|
|
||||||
try {
|
function getExecutablePath(): string {
|
||||||
|
const config = vscode.workspace.getConfiguration("hblang");
|
||||||
|
return config.get<string>("compilerPath") === "Use PATH"
|
||||||
|
? DEFAULT_EXECUTABLE
|
||||||
|
: config.get<string>("compilerPath")!;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runCommand(filePath: string, args: string[]): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
execFile(getExecutablePath(), args, (error, stdout, stderr) => {
|
||||||
|
if (error && error.code === "ENOENT") {
|
||||||
|
vscode.window.showErrorMessage(
|
||||||
|
"hblang compiler not found. Ensure 'hbc' is installed and available in PATH."
|
||||||
|
);
|
||||||
|
return reject(new Error(`Compiler not found: ${stderr || stdout}`));
|
||||||
|
}
|
||||||
|
return error
|
||||||
|
? reject(new Error(stderr || `Exit code: ${error.code}`))
|
||||||
|
: resolve(stdout);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function provideDocumentFormattingEdits(
|
||||||
|
document: vscode.TextDocument
|
||||||
|
): Promise<vscode.TextEdit[]> {
|
||||||
|
const tempFilePath = path.join(
|
||||||
|
path.dirname(document.uri.fsPath),
|
||||||
|
`temp_${path.basename(document.uri.fsPath)}`
|
||||||
|
);
|
||||||
await fs.promises.writeFile(tempFilePath, document.getText());
|
await fs.promises.writeFile(tempFilePath, document.getText());
|
||||||
|
|
||||||
const stdout = await new Promise<string>((resolve, reject) => {
|
try {
|
||||||
execFile('hbc', ['--fmt-stdout', tempFilePath], (error, stdout, stderr) => {
|
const stdout = await runCommand(tempFilePath, [
|
||||||
if (error) {
|
"--fmt-stdout",
|
||||||
if (error.code === 'ENOENT') {
|
tempFilePath,
|
||||||
vscode.window.showErrorMessage("hblang compiler not found. ensure 'hbc' is installed and available in PATH.");
|
]);
|
||||||
} else {
|
|
||||||
vscode.window.showErrorMessage(`error formatting document with hbc: ${stderr || `exit code: ${error.code}`}`);
|
|
||||||
}
|
|
||||||
return reject(new Error(stderr || `exit code: ${error.code}`));
|
|
||||||
}
|
|
||||||
resolve(stdout);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const fullRange = new vscode.Range(
|
const fullRange = new vscode.Range(
|
||||||
document.positionAt(0),
|
document.positionAt(0),
|
||||||
document.positionAt(document.getText().length)
|
document.positionAt(document.getText().length)
|
||||||
);
|
);
|
||||||
const edit = vscode.TextEdit.replace(fullRange, stdout);
|
|
||||||
return [edit];
|
|
||||||
|
|
||||||
|
diagnosticCollection.delete(document.uri);
|
||||||
|
|
||||||
|
return [vscode.TextEdit.replace(fullRange, stdout)];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
if (error instanceof Error && error.message.includes('ENOENT')) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const message = error instanceof Error ? error.message : 'unknown error occurred.';
|
|
||||||
vscode.window.showErrorMessage(`error formatting document: ${message}`);
|
|
||||||
return [];
|
return [];
|
||||||
} finally {
|
} finally {
|
||||||
fs.promises.unlink(tempFilePath).catch((err) => {
|
fs.promises.unlink(tempFilePath).catch(console.error);
|
||||||
console.error('error removing temp file:', err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let diagnosticCollection: vscode.DiagnosticCollection;
|
|
||||||
|
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
|
||||||
diagnosticCollection = vscode.languages.createDiagnosticCollection('hblang');
|
|
||||||
context.subscriptions.push(diagnosticCollection);
|
|
||||||
|
|
||||||
vscode.workspace.onDidSaveTextDocument(onDocumentSaved);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onDocumentSaved(document: vscode.TextDocument) {
|
|
||||||
if (document.languageId === 'hblang') {
|
|
||||||
await lintDocument(document);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function lintDocument(document: vscode.TextDocument) {
|
async function lintDocument(document: vscode.TextDocument) {
|
||||||
const filePath = document.uri.fsPath;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stderr = await runCompiler(filePath);
|
const stderr = await runCommand(document.uri.fsPath, [document.uri.fsPath]);
|
||||||
const diagnostics = parseLintingErrors(stderr);
|
diagnosticCollection.set(document.uri, parseLintingErrors(stderr));
|
||||||
diagnosticCollection.set(document.uri, diagnostics);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
const diagnostics = parseLintingErrors(error.message);
|
diagnosticCollection.set(document.uri, parseLintingErrors(error.message));
|
||||||
diagnosticCollection.set(document.uri, diagnostics);
|
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showErrorMessage(`error linting hblang document for some reason`)
|
vscode.window.showErrorMessage("Error linting hblang document.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runCompiler(filePath: string): Promise<string> {
|
|
||||||
return new Promise<string>((resolve, reject) => {
|
|
||||||
execFile('hbc', [filePath], (error, stdout, stderr) => {
|
|
||||||
if (error) {
|
|
||||||
if (error.code === 'ENOENT') {
|
|
||||||
|
|
||||||
vscode.window.showErrorMessage("hblang compiler not found. ensure 'hbc' is installed and available in PATH.");
|
|
||||||
}
|
|
||||||
reject(new Error(stderr || `Exit code: ${error.code}`));
|
|
||||||
} else {
|
|
||||||
resolve(stderr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseLintingErrors(stderr: string): vscode.Diagnostic[] {
|
function parseLintingErrors(stderr: string): vscode.Diagnostic[] {
|
||||||
const diagnostics: vscode.Diagnostic[] = [];
|
return stderr
|
||||||
const lines = stderr.trim().split('\n');
|
.split("\n")
|
||||||
|
.filter((line) => line && !line.includes("missing main function"))
|
||||||
|
.map((lineText) => {
|
||||||
|
const match = lineText.match(/^([^:]+):(\d+):(\d+):\s*(.+)$/);
|
||||||
|
if (!match) return null;
|
||||||
|
|
||||||
for (const line of lines) {
|
const [, , lineStr, columnStr, message] = match;
|
||||||
const match = line.match(/^([^:]+):(\d+):(\d+):\s*(.+)$/);
|
const lineNum = parseInt(lineStr, 10) - 1;
|
||||||
if (match && !line.includes('missing main function')) {
|
const columnNum = parseInt(columnStr, 10) - 1;
|
||||||
const [, filePath, lineStr, columnStr, message] = match;
|
|
||||||
const line = parseInt(lineStr, 10) - 1;
|
return new vscode.Diagnostic(
|
||||||
const column = parseInt(columnStr, 10) - 1;
|
new vscode.Range(
|
||||||
const diagnostic = new vscode.Diagnostic(
|
lineNum,
|
||||||
new vscode.Range(line, column, line, column + message.length),
|
columnNum,
|
||||||
|
lineNum,
|
||||||
|
columnNum + message.length
|
||||||
|
),
|
||||||
message,
|
message,
|
||||||
vscode.DiagnosticSeverity.Error
|
vscode.DiagnosticSeverity.Error
|
||||||
);
|
);
|
||||||
diagnostic.source = 'hbc';
|
})
|
||||||
diagnostics.push(diagnostic);
|
.filter(Boolean) as vscode.Diagnostic[];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
return diagnostics;
|
diagnosticCollection = vscode.languages.createDiagnosticCollection("hblang");
|
||||||
|
context.subscriptions.push(diagnosticCollection);
|
||||||
|
|
||||||
|
vscode.workspace.onDidSaveTextDocument(async (document) => {
|
||||||
|
if (document.languageId === "hblang") {
|
||||||
|
await lintDocument(document);
|
||||||
|
|
||||||
|
if (diagnosticCollection.get(document.uri)?.length === 0) {
|
||||||
|
vscode.commands.executeCommand(
|
||||||
|
"editor.action.formatDocument",
|
||||||
|
document
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
vscode.languages.registerDocumentFormattingEditProvider("hblang", {
|
||||||
|
provideDocumentFormattingEdits,
|
||||||
|
});
|
||||||
}
|
}
|
3
tests/dont-erase.hb
Normal file
3
tests/dont-erase.hb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
main := fn(): void {
|
||||||
|
undefined_identifier
|
||||||
|
}
|
Loading…
Reference in a new issue