Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Verilog-HDL formatting with iStyle Verilog Formatter #365

Merged
merged 1 commit into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
## [1.6.1] - Unreleased

- Added experimental support for Verilog-HDL formatting with [verilog-format](https://github.com/ericsonj/verilog-format).
- Added experimental support for Verilog-HDL formatting with [thomasrussellmurphy/istyle-verilog-formatter: Open source implementation of a Verilog formatter](https://github.com/thomasrussellmurphy/istyle-verilog-formatter).

## [1.6.0] - 2022-12-20

Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ Use the following settings to configure the extension to your needs

\[Experimental\] A path to the HDL Checker Language Server binary.

"verilog.formatter.name": {
"scope": "window",
"type": "string",
"enum": [
"verilog-format",
"iStyle"
],
"default": "verilog-format",
"description": "[Experimental] Choose a Verilog-HDL formatter."
},
- `verilog.formatter.verilogHDL.name` (Default: `verilog-format`)

\[Experimental\] Choose a Verilog-HDL formatter.

- `verilog.formatter.verilogFormat.path` (Default: `verilog-format`)

\[Experimental\] A path to the verilog-format binary.
Expand All @@ -144,6 +158,18 @@ Use the following settings to configure the extension to your needs

\[Experimental\] A path to the verilog-format settings file.

- `verilog.formatter.iStyleVerilogFormatter.path` (Default: `iStyle`)

\[Experimental\] A path to the iStyle Verilog Formatter binary.

- `verilog.formatter.iStyleVerilogFormatter.arguments` (Default: nothing)

\[Experimental\] Add custom arguments to iStyle Verilog Formatter for formatting.

- `verilog.formatter.iStyleVerilogFormatter.style` (Default: `Indent only`)

\[Experimental\] Choose styling options from ANSI/K&R/GNU.

## Commands

- **Rerun lint tool**
Expand Down
34 changes: 34 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,16 @@
"default": "hdl_checker",
"description": "[Experimental] A path to the HDL Checker Language Server binary."
},
"verilog.formatter.verilogHDL.name": {
"scope": "window",
"type": "string",
"enum": [
"verilog-format",
"iStyle"
],
"default": "verilog-format",
"description": "[Experimental] Choose a Verilog-HDL formatter."
},
"verilog.formatter.verilogFormat.path": {
"scope": "window",
"type": "string",
Expand All @@ -330,6 +340,30 @@
"type": "string",
"default": "${env:HOME}/.verilog-format.properties",
"description": "[Experimental] A path to the verilog-format settings file."
},
"verilog.formatter.iStyleVerilogFormatter.path": {
"scope": "window",
"type": "string",
"default": "iStyle",
"description": "[Experimental] A path to the iStyle Verilog Formatter binary."
},
"verilog.formatter.iStyleVerilogFormatter.arguments": {
"scope": "window",
"type": "string",
"default": "",
"description": "[Experimental] Add custom arguments to iStyle Verilog Formatter for formatting."
},
"verilog.formatter.iStyleVerilogFormatter.style": {
"scope": "window",
"type": "string",
"enum": [
"ANSI",
"K&R",
"GNU",
"Indent only"
],
"default": "Indent only",
"description": "[Experimental] Choose styling options from ANSI/K&R/GNU."
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ export function activate(context: vscode.ExtensionContext) {
);

// Configure Format Provider
let formatProvider = new FormatProvider.VerilogFormatProvider(logger);
let verilogFormatProvider = new FormatProvider.VerilogFormatProvider(logger);
context.subscriptions.push(
vscode.languages.registerDocumentFormattingEditProvider(verilogSelector, formatProvider)
vscode.languages.registerDocumentFormattingEditProvider(verilogSelector, verilogFormatProvider)
);

// Configure command to instantiate a module
Expand Down
136 changes: 102 additions & 34 deletions src/providers/FormatPrivider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,101 @@ import * as crypto from 'crypto';
import * as path from 'path';
import { Logger, LogSeverity } from '../logger';

function formatWithVerilogFormat(document: vscode.TextDocument, logger: Logger): vscode.ProviderResult<vscode.TextEdit[]> {
// grab config from verilog.formatter
let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('verilog.formatter.verilogFormat');
let binPath: string = <string>(settings.get("path", "verilog-format"));
let settingsPath: string | null = <string>(settings.get("settings", null));

// create temporary file and copy document to it
let tempFilepath: string = path.join(os.tmpdir(), "verilog-format-" + crypto.randomBytes(16).toString('hex') + ".tmp.v");
fs.writeFileSync(tempFilepath, document.getText(), { flag: "w" });
logger.log("[Verilog-Format] Temp file created at:" + tempFilepath);

var args: string[] = ["-f", tempFilepath];

if (settingsPath !== null && fs.existsSync(settingsPath)) {
args.push("-s");
args.push(settingsPath);
}

// execute command
logger.log("[Verilog-Format] Executing command: " + binPath + " " + args.join(" "));
try {
child_process.execFileSync(binPath, args, {});

let formattedText: string = fs.readFileSync(tempFilepath, { encoding: "utf-8" });
let wholeFileRange: vscode.Range = new vscode.Range(
document.positionAt(0),
document.positionAt(document.getText().length));
fs.rmSync(tempFilepath);

return [vscode.TextEdit.replace(wholeFileRange, formattedText)];
} catch (err) {
logger.log("[Verilog-Format] " + err.toString(), LogSeverity.error);
}

if (fs.existsSync(tempFilepath)) {
fs.rmSync(tempFilepath);
}
return [];
}

function formatWithIStyleVerilogFormatter(document: vscode.TextDocument, logger: Logger): vscode.ProviderResult<vscode.TextEdit[]> {
// grab config from verilog.iStyleVerilogFormatter
let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('verilog.formatter.iStyleVerilogFormatter');
let binPath: string = <string>(settings.get("path", "iStyle"));
let customArgs: string = <string>(settings.get("arguments", ""));
let formatStyle: string = <string>(settings.get("style", "Indent only"));

// create temporary file and copy document to it
let tempFilepath: string = path.join(os.tmpdir(), "istyle-verilog-format-" + crypto.randomBytes(16).toString('hex') + ".tmp.v");
fs.writeFileSync(tempFilepath, document.getText(), { flag: "w" });
logger.log("[iStyle-Formatter] Temp file created at:" + tempFilepath);

// -n means not to create a .orig file
var args: string[] = ["-n"];
if (customArgs.length > 0) {
args = args.concat(customArgs.split(" "));
}

// format style
switch (formatStyle) {
case "ANSI":
args.push("--style=ansi");
break;
case "K&R":
args.push("--style=kr");
break;
case "GNU":
args.push("--style=gnu");
break;
}

args.push(tempFilepath);

// execute command
logger.log("[iStyle-Formater] Executing command: " + binPath + " " + args.join(" "));
try {
child_process.execFileSync(binPath, args, {});

let formattedText: string = fs.readFileSync(tempFilepath, { encoding: "utf-8" });
let wholeFileRange: vscode.Range = new vscode.Range(
document.positionAt(0),
document.positionAt(document.getText().length));
fs.rmSync(tempFilepath);

return [vscode.TextEdit.replace(wholeFileRange, formattedText)];
} catch (err) {
logger.log("[iStyle-Formatter] " + err.toString(), LogSeverity.error);
}

if (fs.existsSync(tempFilepath)) {
fs.rmSync(tempFilepath);
}
return [];
}

export class VerilogFormatProvider implements vscode.DocumentFormattingEditProvider {
private logger: Logger;

Expand All @@ -18,41 +113,14 @@ export class VerilogFormatProvider implements vscode.DocumentFormattingEditProvi
_options: vscode.FormattingOptions,
_token: vscode.CancellationToken
): vscode.ProviderResult<vscode.TextEdit[]> {
// grab config from verilog.formatter
let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('verilog.formatter');
let binPath: string = <string>(settings.get("path", "verilog-format"));
let settingsPath: string | null = <string>(settings.get("settings", null));

// create temporary file and copy document to it
let tempFilepath: string = path.join(os.tmpdir(), "verilog-format-" + crypto.randomBytes(16).toString('hex') + ".tmp.v");
fs.writeFileSync(tempFilepath, document.getText(), { flag: "w" });
this.logger.log("[Verilog-Format] Temp file created at:" + tempFilepath);

var args: string[] = ["-f", tempFilepath];

if (settingsPath !== null && fs.existsSync(settingsPath)) {
args.push("-s");
args.push(settingsPath);
}

// execute command
this.logger.log("[Verilog-Format] Executing command: " + binPath + " " + args.join(" "));
try {
child_process.execFileSync(binPath, args, {});

let formattedText: string = fs.readFileSync(tempFilepath, { encoding: "utf-8" });
let wholeFileRange: vscode.Range = new vscode.Range(
document.positionAt(0),
document.positionAt(document.getText().length));
fs.rmSync(tempFilepath);

return [vscode.TextEdit.replace(wholeFileRange, formattedText)];
} catch (err) {
this.logger.log("[Verilog-Format] Error on verilog-format: " + err.toString(), LogSeverity.error);
}
let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('verilog.formatter.verilogHDL');
let formatter: string | null = <string>(settings.get("name", null));

if (fs.existsSync(tempFilepath)) {
fs.rmSync(tempFilepath);
switch (formatter) {
case "verilog-format":
return formatWithVerilogFormat(document, this.logger);
case "iStyle":
return formatWithIStyleVerilogFormatter(document, this.logger);
}
return [];
}
Expand Down