From fe90ed730ca8218597978c404eba353ccfa25f79 Mon Sep 17 00:00:00 2001
From: Kirigaya <1193466151@qq.com>
Date: Mon, 11 Dec 2023 23:04:22 +0800
Subject: [PATCH] finish linter for sv
---
.vscodeignore | 3 +-
design/lsp.drawio | 120 ++++++++++++++++++
package.json | 20 +++
package.nls.json | 1 +
package.nls.zh-cn.json | 1 +
package.nls.zh-tw.json | 1 +
script/test/svlogAll.js | 8 ++
src/function/index.ts | 2 +
src/function/lsp/linter/command.ts | 39 +++++-
src/function/lsp/linter/index.ts | 7 +-
src/function/lsp/linter/svlog.ts | 192 +++++++++++++++++++++++++++++
src/monitor/event.ts | 7 +-
12 files changed, 394 insertions(+), 7 deletions(-)
create mode 100644 design/lsp.drawio
create mode 100644 script/test/svlogAll.js
create mode 100644 src/function/lsp/linter/svlog.ts
diff --git a/.vscodeignore b/.vscodeignore
index 3a191d2..ce086d0 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -13,4 +13,5 @@ script
resources/**/*.js
resources/**/*.d.ts
resources/**/*.wasm
-tsconfig.json
\ No newline at end of file
+tsconfig.json
+design
\ No newline at end of file
diff --git a/design/lsp.drawio b/design/lsp.drawio
new file mode 100644
index 0000000..d39d93f
--- /dev/null
+++ b/design/lsp.drawio
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index ca3f4a9..2bafa7b 100644
--- a/package.json
+++ b/package.json
@@ -238,6 +238,21 @@
"default": "default",
"description": "choose diagnostor to do linter in editing verilog"
},
+ "digital-ide.function.lsp.linter.svlog.diagnostor": {
+ "type": "string",
+ "enumDescriptions": [
+ "use diagnostor in vivado",
+ "use diagnostor in modelsim",
+ "use our buildin diagnostor"
+ ],
+ "enum": [
+ "vivado",
+ "modelsim",
+ "default"
+ ],
+ "default": "default",
+ "description": "choose diagnostor to do linter in editing verilog"
+ },
"digital-ide.function.lsp.linter.vhdl.diagnostor": {
"type": "string",
"enumDescriptions": [
@@ -504,6 +519,11 @@
"category": "Digital-IDE",
"title": "%digital-ide.lsp.vlog.linter.pick.title%"
},
+ {
+ "command": "digital-ide.lsp.svlog.linter.pick",
+ "category": "Digital-IDE",
+ "title": "%digital-ide.lsp.svlog.linter.pick.title%"
+ },
{
"command": "digital-ide.lsp.vhdl.linter.pick",
"category": "Digital-IDE",
diff --git a/package.nls.json b/package.nls.json
index 8c7d739..89c3d6c 100644
--- a/package.nls.json
+++ b/package.nls.json
@@ -42,6 +42,7 @@
"digital-ide.fsm.show.title": "Show FSM graph of current file",
"digital-ide.netlist.show.title": "Show netlist of current file",
"digital-ide.lsp.vlog.linter.pick.title": "select a diagnostic for verilog",
+ "digital-ide.lsp.svlog.linter.pick.title": "select a diagnostic for systemverilog verilog",
"digital-ide.lsp.vhdl.linter.pick.title": "select a diagnostic for vhdl",
"digital-ide.lsp.systemverilog.linter.pick.title": "select a diagnostic for systemverilog"
}
\ No newline at end of file
diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json
index ed5abd0..3e4cd00 100644
--- a/package.nls.zh-cn.json
+++ b/package.nls.zh-cn.json
@@ -42,6 +42,7 @@
"digital-ide.fsm.show.title": "显示当前文件的FSM图",
"digital-ide.netlist.show.title": "显示当前文件的netlist",
"digital-ide.lsp.vlog.linter.pick.title": "选择 Verilog 的诊断",
+ "digital-ide.lsp.svlog.linter.pick.title": "选择 System Verilog 的诊断",
"digital-ide.lsp.vhdl.linter.pick.title": "选择 VHDL 的诊断",
"digital-ide.lsp.systemverilog.linter.pick.title": "选择 SystemVerilog 的诊断"
}
\ No newline at end of file
diff --git a/package.nls.zh-tw.json b/package.nls.zh-tw.json
index 9670943..5404e02 100644
--- a/package.nls.zh-tw.json
+++ b/package.nls.zh-tw.json
@@ -42,6 +42,7 @@
"digital-ide.fsm.show.title": "顯示當前文件的FSM圖",
"digital-ide.netlist.show.title": "顯示當前文件的netlist",
"digital-ide.lsp.vlog.linter.pick.title": "選擇 Verilog 的診斷",
+ "digital-ide.lsp.svlog.linter.pick.title": "選擇 System Verilog 的診斷",
"digital-ide.lsp.vhdl.linter.pick.title": "選擇 VHDL 的診斷",
"digital-ide.lsp.systemverilog.linter.pick.title": "選擇 SystemVerilog 的診斷"
}
\ No newline at end of file
diff --git a/script/test/svlogAll.js b/script/test/svlogAll.js
new file mode 100644
index 0000000..e545415
--- /dev/null
+++ b/script/test/svlogAll.js
@@ -0,0 +1,8 @@
+const { svAll } = require('../../resources/hdlParser');
+
+const testFile = '../Digital-Test/svlog/user/src/hello.sv';
+
+(async () => {
+ const all = await svAll(testFile);
+ console.log(JSON.stringify(all, null, ' '));
+})();
\ No newline at end of file
diff --git a/src/function/index.ts b/src/function/index.ts
index efb542f..ad2be4f 100644
--- a/src/function/index.ts
+++ b/src/function/index.ts
@@ -97,9 +97,11 @@ function registerLsp(context: vscode.ExtensionContext) {
lspCore.hdlSymbolStorage.initialise();
lspLinter.vlogLinterManager.initialise();
lspLinter.vhdlLinterManager.initialise();
+ lspLinter.svlogLinterManager.initialise();
vscode.commands.registerCommand('digital-ide.lsp.vlog.linter.pick', lspLinter.pickVlogLinter);
vscode.commands.registerCommand('digital-ide.lsp.vhdl.linter.pick', lspLinter.pickVhdlLinter);
+ vscode.commands.registerCommand('digital-ide.lsp.svlog.linter.pick', lspLinter.pickSvlogLinter);
}
diff --git a/src/function/lsp/linter/command.ts b/src/function/lsp/linter/command.ts
index a2e572f..3c07979 100644
--- a/src/function/lsp/linter/command.ts
+++ b/src/function/lsp/linter/command.ts
@@ -108,6 +108,42 @@ async function pickVlogLinter() {
pickWidget.show();
}
+
+async function pickSvlogLinter() {
+ const pickWidget = vscode.window.createQuickPick();
+ pickWidget.placeholder = 'select a linter for verilog code diagnostic';
+ pickWidget.canSelectMany = false;
+
+ await vscode.window.withProgress({
+ location: vscode.ProgressLocation.Notification,
+ title: 'Parsing local environment ...',
+ cancellable: true
+ }, async () => {
+ pickWidget.items = [
+ // TODO : add this if system verilog is supported
+ // await makeDefaultPickItem(),
+ await makeVivadoPickItem(HdlLangID.Verilog),
+ await makeModelsimPickItem(HdlLangID.Verilog)
+ ];
+ });
+
+ pickWidget.onDidChangeSelection(items => {
+ const selectedItem = items[0];
+ _selectVlogLinter = selectedItem.name;
+ });
+
+ pickWidget.onDidAccept(() => {
+ if (_selectVlogLinter) {
+ const vlogLspConfig = vscode.workspace.getConfiguration('digital-ide.function.lsp.linter.svlog');
+ vlogLspConfig.update('diagnostor', _selectVlogLinter);
+ pickWidget.hide();
+ }
+ });
+
+ pickWidget.show();
+}
+
+
async function pickVhdlLinter() {
const pickWidget = vscode.window.createQuickPick();
pickWidget.placeholder = 'select a linter for code diagnostic';
@@ -145,5 +181,6 @@ async function pickVhdlLinter() {
export {
pickVlogLinter,
- pickVhdlLinter
+ pickVhdlLinter,
+ pickSvlogLinter
};
\ No newline at end of file
diff --git a/src/function/lsp/linter/index.ts b/src/function/lsp/linter/index.ts
index 1d2b5ee..2c70be1 100644
--- a/src/function/lsp/linter/index.ts
+++ b/src/function/lsp/linter/index.ts
@@ -1,11 +1,14 @@
import { vlogLinterManager } from './vlog';
import { vhdlLinterManager } from './vhdl';
+import { svlogLinterManager } from './svlog';
-import { pickVlogLinter, pickVhdlLinter } from './command';
+import { pickVlogLinter, pickVhdlLinter, pickSvlogLinter } from './command';
export {
vlogLinterManager,
vhdlLinterManager,
+ svlogLinterManager,
pickVlogLinter,
- pickVhdlLinter
+ pickVhdlLinter,
+ pickSvlogLinter,
};
\ No newline at end of file
diff --git a/src/function/lsp/linter/svlog.ts b/src/function/lsp/linter/svlog.ts
new file mode 100644
index 0000000..b2dc942
--- /dev/null
+++ b/src/function/lsp/linter/svlog.ts
@@ -0,0 +1,192 @@
+import * as vscode from 'vscode';
+import { LspOutput, ReportType } from '../../../global';
+import { HdlLangID } from '../../../global/enum';
+import { BaseLinter, BaseManager } from './base';
+import { defaultVlogLinter } from './default';
+import { modelsimLinter } from './modelsim';
+import { vivadoLinter } from './vivado';
+import { hdlFile, hdlPath } from '../../../hdlFs';
+
+class SvlogLinterManager implements BaseManager {
+ currentLinter: BaseLinter | undefined;
+ activateLinterName: string;
+ statusBarItem: vscode.StatusBarItem;
+ initialized: boolean;
+
+ constructor() {
+ this.activateLinterName = 'default';
+ this.initialized = false;
+
+ // make a status bar for rendering
+ this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
+ this.statusBarItem.command = 'digital-ide.lsp.svlog.linter.pick';
+
+ // when changing file, hide if langID is not verilog
+ vscode.window.onDidChangeActiveTextEditor(editor => {
+ if (!editor) {
+ return;
+ }
+ const currentFileName = hdlPath.toSlash(editor.document.fileName);
+
+ if (hdlFile.isSystemVerilogFile(currentFileName)) {
+ this.statusBarItem.show();
+ } else {
+ this.statusBarItem.hide();
+ }
+ });
+
+ // update when user's config is changed
+ vscode.workspace.onDidChangeConfiguration(() => {
+ this.updateLinter();
+ });
+ }
+
+ async initialise(): Promise {
+ const success = await this.updateLinter();
+
+ if (!success) {
+ return;
+ }
+
+ this.initialized = true;
+
+ for (const doc of vscode.workspace.textDocuments) {
+ const fileName = hdlPath.toSlash(doc.fileName);
+ if (hdlFile.isSystemVerilogFile(fileName)) {
+ await this.lint(doc);
+ }
+ }
+ LspOutput.report(' finish initialization of svlog linter. Linter name: ' + this.activateLinterName, ReportType.Launch);
+
+ // hide it if current window is not verilog
+ const editor = vscode.window.activeTextEditor;
+ if (editor && hdlFile.isSystemVerilogFile(editor.document.fileName)) {
+ this.statusBarItem.show();
+ } else {
+ this.statusBarItem.hide();
+ }
+ }
+
+ async lint(document: vscode.TextDocument) {
+ this.currentLinter?.remove(document.uri);
+ await this.currentLinter?.lint(document);
+ }
+
+ async remove(uri: vscode.Uri): Promise {
+ this.currentLinter?.remove(uri);
+ }
+
+ public getUserDiagnostorSelection() {
+ const vlogLspConfig = vscode.workspace.getConfiguration('digital-ide.function.lsp.linter.svlog');
+ const diagnostor = vlogLspConfig.get('diagnostor', 'xxx');
+ return diagnostor;
+ }
+
+ public async updateLinter(): Promise {
+ const diagnostorName = this.getUserDiagnostorSelection();
+
+ const lastDiagnostorName = this.activateLinterName;
+ const lastDiagnostor = this.currentLinter;
+
+ if (this.initialized && diagnostorName === lastDiagnostorName) {
+ // no need for update
+ return true;
+ }
+ LspOutput.report(` detect linter setting changes, switch from ${lastDiagnostorName} to ${diagnostorName}.`, ReportType.Launch);
+
+ let launch = false;
+ switch (diagnostorName) {
+ case 'vivado': launch = await this.activateVivado(); break;
+ case 'modelsim': launch = await this.activateModelsim(); break;
+ case 'default': launch = await this.activateDefault(); break;
+ default: launch = await this.activateDefault(); break;
+ }
+
+ for (const doc of vscode.workspace.textDocuments) {
+ const fileName = hdlPath.toSlash(doc.fileName);
+ if (hdlFile.isSystemVerilogFile(fileName)) {
+ lastDiagnostor?.remove(doc.uri);
+ await this.lint(doc);
+ }
+ }
+
+ return launch;
+ }
+
+ public async activateVivado(): Promise {
+ const selectedLinter = vivadoLinter;
+ let launch = true;
+
+ launch = await selectedLinter.initialise(HdlLangID.SystemVerilog);
+ if (launch) {
+ this.statusBarItem.text = '$(getting-started-beginner) Linter(vivado)';
+
+ LspOutput.report(' vivado linter has been activated', ReportType.Info);
+ } else {
+ this.statusBarItem.backgroundColor = new vscode.ThemeColor('statusBarItem.warningBackground');
+ this.statusBarItem.tooltip = 'Fail to launch vivado linter';
+ this.statusBarItem.text = '$(extensions-warning-message) Linter(vivado)';
+
+ LspOutput.report(' Fail to launch vivado linter', ReportType.Error);
+ }
+
+ this.currentLinter = selectedLinter;
+ this.activateLinterName = 'vivado';
+ this.statusBarItem.show();
+
+ return launch;
+ }
+
+ public async activateModelsim(): Promise {
+ const selectedLinter = modelsimLinter;
+ let launch = true;
+
+ launch = await selectedLinter.initialise(HdlLangID.SystemVerilog);
+ if (launch) {
+ this.statusBarItem.text = '$(getting-started-beginner) Linter(modelsim)';
+
+ LspOutput.report(' modelsim linter has been activated', ReportType.Info);
+ } else {
+ this.statusBarItem.backgroundColor = new vscode.ThemeColor('statusBarItem.warningBackground');
+ this.statusBarItem.tooltip = 'Fail to launch modelsim linter';
+ this.statusBarItem.text = '$(extensions-warning-message) Linter(modelsim)';
+
+ LspOutput.report(' Fail to launch modelsim linter', ReportType.Error);
+ }
+
+ this.currentLinter = selectedLinter;
+ this.activateLinterName = 'modelsim';
+ this.statusBarItem.show();
+
+ return launch;
+ }
+
+ public async activateDefault(): Promise {
+ const selectedLinter = defaultVlogLinter;
+ let launch = true;
+
+ if (launch) {
+ this.statusBarItem.text = '$(getting-started-beginner) Linter(default)';
+
+ LspOutput.report(' default build-in linter has been activated', ReportType.Info);
+ } else {
+ this.statusBarItem.backgroundColor = undefined;
+ this.statusBarItem.tooltip = 'Fail to launch default linter';
+ this.statusBarItem.text = '$(extensions-warning-message) Linter(default)';
+
+ LspOutput.report(' Fail to launch default linter', ReportType.Error);
+ }
+
+ this.currentLinter = selectedLinter;
+ this.activateLinterName = 'default';
+ this.statusBarItem.show();
+
+ return launch;
+ }
+}
+
+const svlogLinterManager = new SvlogLinterManager();
+
+export {
+ svlogLinterManager
+};
diff --git a/src/monitor/event.ts b/src/monitor/event.ts
index e4019f5..2aee56f 100644
--- a/src/monitor/event.ts
+++ b/src/monitor/event.ts
@@ -14,8 +14,7 @@ import { libManage } from '../manager/lib';
import type { HdlMonitor } from './index';
import { HdlLangID, ToolChainType } from '../global/enum';
import { hdlSymbolStorage } from '../function/lsp/core';
-import { vlogLinterManager, vhdlLinterManager } from '../function/lsp/linter';
-import { isVerilogFile } from '../hdlFs/file';
+import { vlogLinterManager, vhdlLinterManager, svlogLinterManager } from '../function/lsp/linter';
enum Event {
Add = 'add', // emit when add file
@@ -102,6 +101,8 @@ class HdlAction extends BaseAction {
vlogLinterManager.remove(uri);
} else if (langID === HdlLangID.Vhdl) {
vhdlLinterManager.remove(uri);
+ } else if (langID === HdlLangID.SystemVerilog) {
+ svlogLinterManager.remove(uri);
}
}
@@ -141,7 +142,7 @@ class HdlAction extends BaseAction {
} else if (langID === HdlLangID.Vhdl) {
vhdlLinterManager.lint(document);
} else if (langID === HdlLangID.SystemVerilog) {
- // TODO
+ svlogLinterManager.lint(document);
}
}