From 56d6db197860d7e7e6d4a28a34ece881de2ea678 Mon Sep 17 00:00:00 2001 From: Masahiro Hiramori Date: Wed, 21 Dec 2022 21:19:06 +0900 Subject: [PATCH] implement iStyle formatter --- CHANGELOG.md | 1 + README.md | 26 ++++++ package.json | 34 ++++++++ src/extension.ts | 4 +- src/providers/FormatPrivider.ts | 136 ++++++++++++++++++++++++-------- 5 files changed, 165 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac067fef..235385bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index 7d9be2c6..5a5d3b73 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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** diff --git a/package.json b/package.json index 0540ff3c..f911ee8e 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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." } } }, diff --git a/src/extension.ts b/src/extension.ts index 66ac904c..998cb1a1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -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 diff --git a/src/providers/FormatPrivider.ts b/src/providers/FormatPrivider.ts index 038bd32c..467fd810 100644 --- a/src/providers/FormatPrivider.ts +++ b/src/providers/FormatPrivider.ts @@ -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 { + // grab config from verilog.formatter + let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('verilog.formatter.verilogFormat'); + let binPath: string = (settings.get("path", "verilog-format")); + let settingsPath: string | null = (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 { + // grab config from verilog.iStyleVerilogFormatter + let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('verilog.formatter.iStyleVerilogFormatter'); + let binPath: string = (settings.get("path", "iStyle")); + let customArgs: string = (settings.get("arguments", "")); + let formatStyle: 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; @@ -18,41 +113,14 @@ export class VerilogFormatProvider implements vscode.DocumentFormattingEditProvi _options: vscode.FormattingOptions, _token: vscode.CancellationToken ): vscode.ProviderResult { - // grab config from verilog.formatter - let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('verilog.formatter'); - let binPath: string = (settings.get("path", "verilog-format")); - let settingsPath: string | null = (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 = (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 []; }