实现三种诊断模式
This commit is contained in:
parent
0dd947addd
commit
758a108096
@ -94,5 +94,7 @@
|
|||||||
"error.linter.status-bar.tooltip": "Kann Diagnose für {0} nicht abrufen",
|
"error.linter.status-bar.tooltip": "Kann Diagnose für {0} nicht abrufen",
|
||||||
"info.linter.status-bar.tooltip": "Diagnosegerät {0} arbeitet",
|
"info.linter.status-bar.tooltip": "Diagnosegerät {0} arbeitet",
|
||||||
"warning.linter.cannot-get-valid-linter-invoker": "Die digitale IDE kann keinen Aufrufpfad für {0} abrufen. Bitte installieren Sie den entsprechenden Diagnose-Tool und konfigurieren Sie ihn entweder in der Umgebungsvariablen PATH oder im digitalen IDE-Diagnosetool-Installationspfad.",
|
"warning.linter.cannot-get-valid-linter-invoker": "Die digitale IDE kann keinen Aufrufpfad für {0} abrufen. Bitte installieren Sie den entsprechenden Diagnose-Tool und konfigurieren Sie ihn entweder in der Umgebungsvariablen PATH oder im digitalen IDE-Diagnosetool-Installationspfad.",
|
||||||
"info.linter.config-linter-install-path": "Installationsverzeichnis konfigurieren"
|
"info.linter.config-linter-install-path": "Installationsverzeichnis konfigurieren",
|
||||||
|
"info.progress.doing-diagnostic": "Diagnostizierung",
|
||||||
|
"error.common.fail-to-launch-lsp": "Start des Sprachservers fehlgeschlagen!"
|
||||||
}
|
}
|
@ -94,5 +94,7 @@
|
|||||||
"error.linter.status-bar.tooltip": "Unable to get {0} diagnoser",
|
"error.linter.status-bar.tooltip": "Unable to get {0} diagnoser",
|
||||||
"info.linter.status-bar.tooltip": "Diagnostics {0} is working",
|
"info.linter.status-bar.tooltip": "Diagnostics {0} is working",
|
||||||
"warning.linter.cannot-get-valid-linter-invoker": "The Digital IDE cannot retrieve the call path for {0}. Please install the corresponding diagnostic tool and configure it either in the environment variable PATH or in the Digital IDE's diagnostic tool installation path.",
|
"warning.linter.cannot-get-valid-linter-invoker": "The Digital IDE cannot retrieve the call path for {0}. Please install the corresponding diagnostic tool and configure it either in the environment variable PATH or in the Digital IDE's diagnostic tool installation path.",
|
||||||
"info.linter.config-linter-install-path": "Configure installation directory"
|
"info.linter.config-linter-install-path": "Configure installation directory",
|
||||||
|
"info.progress.doing-diagnostic": "Diagnosing",
|
||||||
|
"error.common.fail-to-launch-lsp": "Language server startup failed!"
|
||||||
}
|
}
|
@ -94,5 +94,7 @@
|
|||||||
"error.linter.status-bar.tooltip": "{0} 診断機能を取得できません",
|
"error.linter.status-bar.tooltip": "{0} 診断機能を取得できません",
|
||||||
"info.linter.status-bar.tooltip": "診断ツール {0} が作動中",
|
"info.linter.status-bar.tooltip": "診断ツール {0} が作動中",
|
||||||
"warning.linter.cannot-get-valid-linter-invoker": "デジタルIDEは{0}の呼び出しパスを取得できません。対応する診断ツールをインストールし、環境変数PATHに設定するか、デジタルIDEの診断ツールインストールパスを設定してください。",
|
"warning.linter.cannot-get-valid-linter-invoker": "デジタルIDEは{0}の呼び出しパスを取得できません。対応する診断ツールをインストールし、環境変数PATHに設定するか、デジタルIDEの診断ツールインストールパスを設定してください。",
|
||||||
"info.linter.config-linter-install-path": "インストールディレクトリを設定"
|
"info.linter.config-linter-install-path": "インストールディレクトリを設定",
|
||||||
|
"info.progress.doing-diagnostic": "診断中",
|
||||||
|
"error.common.fail-to-launch-lsp": "言語サーバーの起動に失敗しました!"
|
||||||
}
|
}
|
@ -94,5 +94,7 @@
|
|||||||
"error.linter.status-bar.tooltip": "无法获取 {0} 诊断器",
|
"error.linter.status-bar.tooltip": "无法获取 {0} 诊断器",
|
||||||
"info.linter.status-bar.tooltip": "诊断器 {0} 正在工作",
|
"info.linter.status-bar.tooltip": "诊断器 {0} 正在工作",
|
||||||
"warning.linter.cannot-get-valid-linter-invoker": "Digital IDE 无法获取到关于 {0} 的调用路径,请安装对应诊断器后,配置到环境变量 PATH 或者配置 Digital IDE 对应的诊断工具安装路径",
|
"warning.linter.cannot-get-valid-linter-invoker": "Digital IDE 无法获取到关于 {0} 的调用路径,请安装对应诊断器后,配置到环境变量 PATH 或者配置 Digital IDE 对应的诊断工具安装路径",
|
||||||
"info.linter.config-linter-install-path": "配置安装目录"
|
"info.linter.config-linter-install-path": "配置安装目录",
|
||||||
|
"info.progress.doing-diagnostic": "诊断中",
|
||||||
|
"error.common.fail-to-launch-lsp": "语言服务器启动失败!"
|
||||||
}
|
}
|
@ -94,5 +94,7 @@
|
|||||||
"error.linter.status-bar.tooltip": "無法取得 {0} 診斷器",
|
"error.linter.status-bar.tooltip": "無法取得 {0} 診斷器",
|
||||||
"info.linter.status-bar.tooltip": "診斷器 {0} 正在運作",
|
"info.linter.status-bar.tooltip": "診斷器 {0} 正在運作",
|
||||||
"warning.linter.cannot-get-valid-linter-invoker": "Digital IDE 無法取得關於 {0} 的呼叫路徑,請安裝對應診斷器後,配置到環境變數 PATH 或者配置 Digital IDE 對應的診斷工具安裝路徑。",
|
"warning.linter.cannot-get-valid-linter-invoker": "Digital IDE 無法取得關於 {0} 的呼叫路徑,請安裝對應診斷器後,配置到環境變數 PATH 或者配置 Digital IDE 對應的診斷工具安裝路徑。",
|
||||||
"info.linter.config-linter-install-path": "配置安裝目錄"
|
"info.linter.config-linter-install-path": "配置安裝目錄",
|
||||||
|
"info.progress.doing-diagnostic": "診斷中",
|
||||||
|
"error.common.fail-to-launch-lsp": "語言伺服器啟動失敗!"
|
||||||
}
|
}
|
@ -293,7 +293,7 @@
|
|||||||
],
|
],
|
||||||
"enum": [
|
"enum": [
|
||||||
"full",
|
"full",
|
||||||
"single",
|
"common",
|
||||||
"shutdown"
|
"shutdown"
|
||||||
],
|
],
|
||||||
"default": "full",
|
"default": "full",
|
||||||
|
@ -4,12 +4,12 @@ import * as fs from 'fs';
|
|||||||
import { MainOutput, ReportType, IProgress } from './global';
|
import { MainOutput, ReportType, IProgress } from './global';
|
||||||
import { hdlParam } from './hdlParser';
|
import { hdlParam } from './hdlParser';
|
||||||
import * as manager from './manager';
|
import * as manager from './manager';
|
||||||
|
import * as lspLinter from './function/lsp/linter';
|
||||||
import * as func from './function';
|
import * as func from './function';
|
||||||
import { hdlMonitor } from './monitor';
|
import { hdlMonitor } from './monitor';
|
||||||
|
|
||||||
import * as lspClient from './function/lsp-client';
|
import * as lspClient from './function/lsp-client';
|
||||||
import { refreshArchTree } from './function/treeView';
|
import { refreshArchTree } from './function/treeView';
|
||||||
import { hdlFile } from './hdlFs';
|
|
||||||
import { initialiseI18n, t } from './i18n';
|
import { initialiseI18n, t } from './i18n';
|
||||||
|
|
||||||
|
|
||||||
@ -85,12 +85,12 @@ async function launch(context: vscode.ExtensionContext) {
|
|||||||
await lspClient.activate(context, packageJson);
|
await lspClient.activate(context, packageJson);
|
||||||
});
|
});
|
||||||
|
|
||||||
await vscode.window.withProgress({
|
const hdlFiles = await vscode.window.withProgress({
|
||||||
location: vscode.ProgressLocation.Window,
|
location: vscode.ProgressLocation.Window,
|
||||||
title: t('info.progress.initialization')
|
title: t('info.progress.initialization')
|
||||||
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||||
// 初始化解析
|
// 初始化解析
|
||||||
await manager.prjManage.initialise(context, progress);
|
const hdlFiles = await manager.prjManage.initialise(context, progress);
|
||||||
|
|
||||||
// 这里是因为 pl 对象在 initialise 完成初始化,此处再注册它的行为
|
// 这里是因为 pl 对象在 initialise 完成初始化,此处再注册它的行为
|
||||||
manager.registerManagerCommands(context);
|
manager.registerManagerCommands(context);
|
||||||
@ -100,9 +100,19 @@ async function launch(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
// 启动监视器
|
// 启动监视器
|
||||||
hdlMonitor.start();
|
hdlMonitor.start();
|
||||||
|
|
||||||
|
return hdlFiles;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
await vscode.window.withProgress({
|
||||||
|
location: vscode.ProgressLocation.Window,
|
||||||
|
title: t('info.progress.doing-diagnostic')
|
||||||
|
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||||
|
// 完成诊断器初始化
|
||||||
|
await lspLinter.initialise(context, hdlFiles, progress);
|
||||||
|
});
|
||||||
|
|
||||||
console.log(hdlParam);
|
console.log(hdlParam);
|
||||||
|
|
||||||
// show welcome information (if first install)
|
// show welcome information (if first install)
|
||||||
|
@ -4,6 +4,10 @@ import { UpdateConfigurationType } from '../../global/lsp';
|
|||||||
import * as Linter from '../lsp/linter/common';
|
import * as Linter from '../lsp/linter/common';
|
||||||
import { HdlLangID } from '../../global/enum';
|
import { HdlLangID } from '../../global/enum';
|
||||||
import * as lspLinter from '../lsp/linter';
|
import * as lspLinter from '../lsp/linter';
|
||||||
|
import { t } from '../../i18n';
|
||||||
|
import { IProgress } from '../../global';
|
||||||
|
import { refreshWorkspaceDiagonastics } from '../lsp/linter/manager';
|
||||||
|
import { prjManage } from '../../manager';
|
||||||
|
|
||||||
interface ConfigItem {
|
interface ConfigItem {
|
||||||
name: string,
|
name: string,
|
||||||
@ -124,6 +128,15 @@ export async function registerConfigurationUpdater(client: LanguageClient, packa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果诊断模式发生变化,进行一次刷新
|
||||||
|
await vscode.window.withProgress({
|
||||||
|
location: vscode.ProgressLocation.Window,
|
||||||
|
title: t('info.progress.doing-diagnostic')
|
||||||
|
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||||
|
const hdlFiles = await prjManage.getPrjHardwareFiles();
|
||||||
|
await refreshWorkspaceDiagonastics(client, hdlFiles, false, progress);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
import { vivadoLinter } from './vivado';
|
|
||||||
import { modelsimLinter } from './modelsim';
|
|
||||||
import { HdlLangID } from '../../../global/enum';
|
import { HdlLangID } from '../../../global/enum';
|
||||||
import { t } from '../../../i18n';
|
import { t } from '../../../i18n';
|
||||||
import { LspClient } from '../../../global';
|
import { LspClient } from '../../../global';
|
||||||
@ -114,7 +112,7 @@ export async function makeLinterOptions(
|
|||||||
|
|
||||||
export enum LinterMode {
|
export enum LinterMode {
|
||||||
Full = 'full',
|
Full = 'full',
|
||||||
Single = 'single',
|
Common = 'common',
|
||||||
Shutdown = 'shutdown'
|
Shutdown = 'shutdown'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,29 @@
|
|||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { AbsPath, IProgress, LspClient } from '../../../global';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
vlogLinterManager,
|
vlogLinterManager,
|
||||||
vhdlLinterManager,
|
vhdlLinterManager,
|
||||||
svlogLinterManager,
|
svlogLinterManager,
|
||||||
reserveLinterManager,
|
reserveLinterManager,
|
||||||
LinterManager
|
LinterManager,
|
||||||
|
refreshWorkspaceDiagonastics
|
||||||
} from './manager';
|
} from './manager';
|
||||||
|
import { t } from '../../../i18n';
|
||||||
|
|
||||||
|
export async function initialise(
|
||||||
|
context: vscode.ExtensionContext,
|
||||||
|
hdlFiles: AbsPath[],
|
||||||
|
progress: vscode.Progress<IProgress>
|
||||||
|
) {
|
||||||
|
const client = LspClient.DigitalIDE;
|
||||||
|
if (!client) {
|
||||||
|
vscode.window.showErrorMessage(t('error.common.fail-to-launch-lsp'));
|
||||||
|
throw Error('初始化失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
await refreshWorkspaceDiagonastics(client, hdlFiles, true, progress);
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
vlogLinterManager,
|
vlogLinterManager,
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { LspClient, LinterOutput, ReportType } from '../../../global';
|
import * as os from 'os';
|
||||||
|
|
||||||
|
import { LspClient, LinterOutput, ReportType, AbsPath, IProgress } from '../../../global';
|
||||||
import { HdlLangID } from '../../../global/enum';
|
import { HdlLangID } from '../../../global/enum';
|
||||||
import { hdlFile, hdlPath } from '../../../hdlFs';
|
import { hdlFile, hdlPath } from '../../../hdlFs';
|
||||||
import { t } from '../../../i18n';
|
import { t } from '../../../i18n';
|
||||||
import { getLinterConfigurationName, getLinterInstallConfigurationName, getLinterName, IConfigReminder, LinterItem, LinterMode, makeLinterNamePickItem, makeLinterOptions, SupportLinterName, updateLinterConfigurationName } from './common';
|
import { getLinterConfigurationName, getLinterInstallConfigurationName, getLinterName, IConfigReminder, LinterItem, LinterMode, makeLinterNamePickItem, makeLinterOptions, SupportLinterName, updateLinterConfigurationName } from './common';
|
||||||
import { UpdateConfigurationType } from '../../../global/lsp';
|
import { UpdateConfigurationType } from '../../../global/lsp';
|
||||||
import { LanguageClient } from 'vscode-languageclient/node';
|
import { LanguageClient } from 'vscode-languageclient/node';
|
||||||
|
import { toEscapePath } from '../../../hdlFs/path';
|
||||||
|
|
||||||
export class LinterManager {
|
export class LinterManager {
|
||||||
/**
|
/**
|
||||||
@ -92,9 +95,6 @@ export class LinterManager {
|
|||||||
// 根据配置选择对应的诊断器
|
// 根据配置选择对应的诊断器
|
||||||
await this.updateCurrentLinterItem(client);
|
await this.updateCurrentLinterItem(client);
|
||||||
|
|
||||||
// TODO: 根据当前的诊断模式进行选择
|
|
||||||
|
|
||||||
|
|
||||||
// 注册内部命令
|
// 注册内部命令
|
||||||
if (!this.started) {
|
if (!this.started) {
|
||||||
const pickerCommand = this.getLinterPickCommand();
|
const pickerCommand = this.getLinterPickCommand();
|
||||||
@ -120,25 +120,6 @@ export class LinterManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 刷新当前工作区所有文件的 linter 状态。仅仅在初始化和更新配置文件时需要使用。
|
|
||||||
*/
|
|
||||||
public async refreshWorkspaceLinterResult(linterMode: LinterMode) {
|
|
||||||
switch (linterMode) {
|
|
||||||
case LinterMode.Full:
|
|
||||||
|
|
||||||
break;
|
|
||||||
case LinterMode.Single:
|
|
||||||
|
|
||||||
break;
|
|
||||||
case LinterMode.Shutdown:
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 更新右下角 status bar 的状态
|
* @description 更新右下角 status bar 的状态
|
||||||
*/
|
*/
|
||||||
@ -264,6 +245,130 @@ export class LinterManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function publishDiagnostics(
|
||||||
|
client: LanguageClient,
|
||||||
|
path: string
|
||||||
|
) {
|
||||||
|
await client.sendRequest("workspace/executeCommand", {
|
||||||
|
command: 'publish-diagnostics',
|
||||||
|
arguments: [path]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function clearDiagnostics(
|
||||||
|
client: LanguageClient,
|
||||||
|
path: string
|
||||||
|
) {
|
||||||
|
await client.sendRequest("workspace/executeCommand", {
|
||||||
|
command: 'clear-diagnostics',
|
||||||
|
arguments: [path]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 异步方法的受限并发消费
|
||||||
|
* @param arrays
|
||||||
|
* @param consumer
|
||||||
|
* @param poolNum
|
||||||
|
*/
|
||||||
|
export async function asyncConsumer<T, R>(
|
||||||
|
arrays: T[],
|
||||||
|
consumer: (item: T) => Promise<R>,
|
||||||
|
poolNum: number,
|
||||||
|
progress?: vscode.Progress<IProgress>
|
||||||
|
): Promise<R[]> {
|
||||||
|
const rets: R[] = [];
|
||||||
|
const pools = [];
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
progress?.report({ message: `${1}/${arrays.length}`, increment: 0 });
|
||||||
|
|
||||||
|
while (i < arrays.length) {
|
||||||
|
const p = consumer(arrays[i]);
|
||||||
|
pools.push({ id: i + 1, promise: p });
|
||||||
|
if (pools.length % poolNum === 0) {
|
||||||
|
for (const p of pools) {
|
||||||
|
const ret = await p.promise;
|
||||||
|
const increment = Math.floor(p.id / arrays.length * 100);
|
||||||
|
progress?.report({ message: `${p.id}/${arrays.length}`, increment });
|
||||||
|
rets.push(ret);
|
||||||
|
}
|
||||||
|
pools.length = 0;
|
||||||
|
}
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const p of pools) {
|
||||||
|
const ret = await p.promise;
|
||||||
|
const increment = Math.floor(p.id / arrays.length * 100);
|
||||||
|
progress?.report({ message: `${p.id}/${arrays.length}`, increment });
|
||||||
|
rets.push(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 刷新当前工作区所有文件的 linter 状态。仅仅在初始化和更新配置文件时需要使用。
|
||||||
|
*/
|
||||||
|
export async function refreshWorkspaceDiagonastics(
|
||||||
|
client: LanguageClient,
|
||||||
|
lintPaths: AbsPath[],
|
||||||
|
isInitialise: boolean,
|
||||||
|
progress: vscode.Progress<IProgress>
|
||||||
|
) {
|
||||||
|
const parallelChunk = Math.min(os.cpus().length, 32);
|
||||||
|
const configuration = vscode.workspace.getConfiguration();
|
||||||
|
const linterMode = configuration.get<LinterMode>('digital-ide.function.lsp.linter.linter-mode', LinterMode.Common);
|
||||||
|
|
||||||
|
console.log('进入诊断,当前诊断模式:', linterMode, lintPaths);
|
||||||
|
|
||||||
|
if (linterMode === LinterMode.Full) {
|
||||||
|
// full,对工作区所有文件进行诊断
|
||||||
|
const consumer = async (path: string) => {
|
||||||
|
await publishDiagnostics(client, path);
|
||||||
|
}
|
||||||
|
await asyncConsumer(lintPaths, consumer, parallelChunk);
|
||||||
|
} else if (linterMode === LinterMode.Common) {
|
||||||
|
// common, 只对打开文件进行操作
|
||||||
|
// 先清除所有的诊断结果
|
||||||
|
const clearConsumer = async (path: string) => {
|
||||||
|
await clearDiagnostics(client, path);
|
||||||
|
}
|
||||||
|
await asyncConsumer(lintPaths, clearConsumer, parallelChunk);
|
||||||
|
|
||||||
|
// 再对激活区域进行诊断
|
||||||
|
const consumer = async (path: string) => {
|
||||||
|
await publishDiagnostics(client, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabs = vscode.window.tabGroups.all;
|
||||||
|
const tabArray = tabs.flatMap<AbsPath>(group => {
|
||||||
|
const files = [];
|
||||||
|
for (const tab of group.tabs) {
|
||||||
|
if (tab.input) {
|
||||||
|
const doc = tab.input as vscode.TabInputText;
|
||||||
|
if (doc.uri) {
|
||||||
|
const absPath = hdlPath.toEscapePath(doc.uri.fsPath);
|
||||||
|
files.push(absPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
await asyncConsumer(tabArray, consumer, parallelChunk);
|
||||||
|
} else {
|
||||||
|
// shutdown, 如果是初始化阶段,什么都不需要做
|
||||||
|
const consumer = async (path: string) => {
|
||||||
|
await clearDiagnostics(client, path);
|
||||||
|
};
|
||||||
|
if (!isInitialise) {
|
||||||
|
await asyncConsumer(lintPaths, consumer, parallelChunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const vlogLinterManager = new LinterManager(HdlLangID.Verilog, [
|
export const vlogLinterManager = new LinterManager(HdlLangID.Verilog, [
|
||||||
'iverilog',
|
'iverilog',
|
||||||
'modelsim',
|
'modelsim',
|
||||||
|
@ -1,200 +0,0 @@
|
|||||||
import * as vscode from "vscode";
|
|
||||||
import * as fs from 'fs';
|
|
||||||
|
|
||||||
import { LinterOutput, ReportType, opeParam } from "../../../global";
|
|
||||||
import { hdlFile, hdlPath } from "../../../hdlFs";
|
|
||||||
import { easyExec } from "../../../global/util";
|
|
||||||
import { HdlLangID } from "../../../global/enum";
|
|
||||||
|
|
||||||
class ModelsimLinter {
|
|
||||||
diagnostic: vscode.DiagnosticCollection;
|
|
||||||
executableFileMap: Map<HdlLangID, string | undefined> = new Map<HdlLangID, string>();
|
|
||||||
executableInvokeNameMap: Map<HdlLangID, string | undefined> = new Map<HdlLangID, string>();
|
|
||||||
linterArgsMap: Map<HdlLangID, string[]> = new Map<HdlLangID, string[]>();
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.diagnostic = vscode.languages.createDiagnosticCollection();
|
|
||||||
|
|
||||||
// configure map for executable file name
|
|
||||||
this.executableFileMap.set(HdlLangID.Verilog, 'vlog');
|
|
||||||
this.executableFileMap.set(HdlLangID.Vhdl, 'vcom');
|
|
||||||
this.executableFileMap.set(HdlLangID.SystemVerilog, 'vlog');
|
|
||||||
this.executableFileMap.set(HdlLangID.Unknown, undefined);
|
|
||||||
|
|
||||||
// configure map for argruments when lintering
|
|
||||||
this.linterArgsMap.set(HdlLangID.Verilog, ['-quiet', '-nologo']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.Vhdl, ['-quiet', '-nologo', '-2008']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.SystemVerilog, ['-quiet', '-nolog', '-sv']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.Unknown, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async lint(document: vscode.TextDocument) {
|
|
||||||
const filePath = hdlPath.toSlash(document.fileName);
|
|
||||||
const langID = hdlFile.getLanguageId(filePath);
|
|
||||||
|
|
||||||
// acquire install path
|
|
||||||
const linterArgs = this.linterArgsMap.get(langID);
|
|
||||||
|
|
||||||
if (linterArgs === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const args = [filePath, ...linterArgs];
|
|
||||||
const executor = this.executableInvokeNameMap.get(langID);
|
|
||||||
if (executor !== undefined) {
|
|
||||||
const { stdout } = await easyExec(executor, args);
|
|
||||||
if (stdout.length > 0) {
|
|
||||||
const diagnostics = this.provideDiagnostics(document, stdout);
|
|
||||||
this.diagnostic.set(document.uri, diagnostics);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LinterOutput.report('modelsim linter is not available, please check prj.modelsim.install.path in your setting!', {
|
|
||||||
level: ReportType.Error,
|
|
||||||
notify: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async remove(uri: vscode.Uri) {
|
|
||||||
this.diagnostic.delete(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param document
|
|
||||||
* @param stdout stdout from xvlog
|
|
||||||
* @returns { vscode.Diagnostic[] } linter info
|
|
||||||
*/
|
|
||||||
private provideDiagnostics(document: vscode.TextDocument, stdout: string): vscode.Diagnostic[] {
|
|
||||||
const diagnostics = [];
|
|
||||||
for (const line of stdout.split(/\r?\n/g)) {
|
|
||||||
const tokens = line.split(/(Error|Warning).+?(?: *?(?:.+?(?:\\|\/))+.+?\((\d+?)\):|)(?: *?near "(.+?)":|)(?: *?\((.+?)\)|) +?(.+)/gm);
|
|
||||||
|
|
||||||
const headerInfo = tokens[1];
|
|
||||||
if (headerInfo === 'Error') {
|
|
||||||
const errorLine = parseInt(tokens[2]) - 1;
|
|
||||||
const syntaxInfo = tokens[5];
|
|
||||||
LinterOutput.report(`<vlog linter> line: ${errorLine}, info: ${syntaxInfo}`, {
|
|
||||||
level: ReportType.Run
|
|
||||||
});
|
|
||||||
|
|
||||||
const range = this.makeCorrectRange(document, errorLine, syntaxInfo);
|
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
|
||||||
diagnostics.push(diag);
|
|
||||||
} else if (headerInfo === 'Warning') {
|
|
||||||
const errorLine = parseInt(tokens[2]) - 1;
|
|
||||||
const syntaxInfo = tokens[5];
|
|
||||||
LinterOutput.report(`<vlog linter> line: ${errorLine}, info: ${syntaxInfo}`, {
|
|
||||||
level: ReportType.Run
|
|
||||||
});
|
|
||||||
|
|
||||||
const range = this.makeCorrectRange(document, errorLine, syntaxInfo);
|
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Warning);
|
|
||||||
diagnostics.push(diag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diagnostics;
|
|
||||||
}
|
|
||||||
|
|
||||||
private makeCorrectRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
|
||||||
// extract all the words like 'adawwd' in a syntax info
|
|
||||||
const singleQuoteWords = syntaxInfo.match(/'([^']*)'/g);
|
|
||||||
if (singleQuoteWords && singleQuoteWords.length > 0) {
|
|
||||||
const targetWord = singleQuoteWords.map(val => val.replace(/'/g, ''))[0];
|
|
||||||
// find range of target word
|
|
||||||
const textLine = document.lineAt(line);
|
|
||||||
const text = textLine.text;
|
|
||||||
const startCharacter = text.indexOf(targetWord);
|
|
||||||
if (startCharacter > -1) {
|
|
||||||
const endCharacter = startCharacter + targetWord.length;
|
|
||||||
const range = new vscode.Range(
|
|
||||||
new vscode.Position(line, startCharacter),
|
|
||||||
new vscode.Position(line, endCharacter)
|
|
||||||
);
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// else target the first word in the line
|
|
||||||
return this.makeCommonRange(document, line, syntaxInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private makeCommonRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
|
||||||
const startPosition = new vscode.Position(line, 0);
|
|
||||||
|
|
||||||
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
|
||||||
if (wordRange) {
|
|
||||||
return wordRange;
|
|
||||||
} else {
|
|
||||||
return new vscode.Range(startPosition, startPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getExecutableFilePath(langID: HdlLangID): string | undefined {
|
|
||||||
// modelsim install path stored in prj.modelsim.install.path
|
|
||||||
const modelsimConfig = vscode.workspace.getConfiguration('digital-ide.prj.modelsim');
|
|
||||||
const modelsimInstallPath = modelsimConfig.get('install.path', '');
|
|
||||||
const executorName = this.executableFileMap.get(langID);
|
|
||||||
if (executorName === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. vlog.exe in windows, vlog in linux
|
|
||||||
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.exe' : executorName;
|
|
||||||
|
|
||||||
if (modelsimInstallPath.trim() === '' || !fs.existsSync(modelsimInstallPath)) {
|
|
||||||
LinterOutput.report(`User's modelsim Install Path "${modelsimInstallPath}", which is invalid. Use ${executorName} in default.`, {
|
|
||||||
level: ReportType.Warn
|
|
||||||
});
|
|
||||||
LinterOutput.report('If you have doubts, check prj.modelsim.install.path in setting', {
|
|
||||||
level: ReportType.Warn
|
|
||||||
});
|
|
||||||
return executorName;
|
|
||||||
} else {
|
|
||||||
LinterOutput.report(`User's modelsim Install Path "${modelsimInstallPath}", which is invalid`);
|
|
||||||
|
|
||||||
const executorPath = hdlPath.join(
|
|
||||||
hdlPath.toSlash(modelsimInstallPath),
|
|
||||||
fullExecutorName
|
|
||||||
);
|
|
||||||
// prevent path like C://stupid name/xxx/xxx/bin
|
|
||||||
// blank space
|
|
||||||
const safeExecutorPath = '"' + executorPath + '"';
|
|
||||||
return safeExecutorPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async setExecutableFilePath(executorPath: string | undefined, langID: HdlLangID): Promise<boolean> {
|
|
||||||
if (executorPath === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { stderr } = await easyExec(executorPath, []);
|
|
||||||
if (stderr.length === 0) {
|
|
||||||
this.executableInvokeNameMap.set(langID, executorPath);
|
|
||||||
LinterOutput.report(`success to verify ${executorPath}, linter from modelsim is ready to go!`, {
|
|
||||||
level: ReportType.Launch
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
this.executableInvokeNameMap.set(langID, undefined);
|
|
||||||
LinterOutput.report(`Fail to execute ${executorPath}! Reason: ${stderr}`, {
|
|
||||||
level: ReportType.Error,
|
|
||||||
notify: true
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async initialise(langID: HdlLangID): Promise<boolean> {
|
|
||||||
const executorPath = this.getExecutableFilePath(langID);
|
|
||||||
return this.setExecutableFilePath(executorPath, langID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const modelsimLinter = new ModelsimLinter();
|
|
||||||
|
|
||||||
export {
|
|
||||||
modelsimLinter,
|
|
||||||
ModelsimLinter
|
|
||||||
};
|
|
@ -1,180 +0,0 @@
|
|||||||
import * as vscode from "vscode";
|
|
||||||
import * as fs from 'fs';
|
|
||||||
|
|
||||||
import { LinterOutput, ReportType, opeParam } from "../../../global";
|
|
||||||
import { hdlFile, hdlPath } from "../../../hdlFs";
|
|
||||||
import { easyExec } from "../../../global/util";
|
|
||||||
import { HdlLangID } from "../../../global/enum";
|
|
||||||
|
|
||||||
type Path = string;
|
|
||||||
|
|
||||||
class VerilatorLinter {
|
|
||||||
diagnostic: vscode.DiagnosticCollection;
|
|
||||||
executableFileMap: Map<HdlLangID, string | undefined> = new Map<HdlLangID, string>();
|
|
||||||
executableInvokeNameMap: Map<HdlLangID, string | undefined> = new Map<HdlLangID, string>();
|
|
||||||
linterArgsMap: Map<HdlLangID, string[]> = new Map<HdlLangID, string[]>();
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.diagnostic = vscode.languages.createDiagnosticCollection();
|
|
||||||
|
|
||||||
// configure map for executable file name
|
|
||||||
this.executableFileMap.set(HdlLangID.Verilog, 'verilator');
|
|
||||||
this.executableFileMap.set(HdlLangID.SystemVerilog, 'verilator');
|
|
||||||
this.executableFileMap.set(HdlLangID.Unknown, undefined);
|
|
||||||
|
|
||||||
// configure map for argruments when lintering
|
|
||||||
this.linterArgsMap.set(HdlLangID.Verilog, ['--lint-only', '-Wall', '-bbox-sys', '--bbox-unsup', '-DGLBL']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.SystemVerilog, ['--lint-only', '-sv', '-Wall', '-bbox-sys', '--bbox-unsup', '-DGLBL']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.Unknown, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async lint(document: vscode.TextDocument) {
|
|
||||||
const filePath = hdlPath.toSlash(document.fileName);
|
|
||||||
const langID = hdlFile.getLanguageId(filePath);
|
|
||||||
|
|
||||||
// acquire install path
|
|
||||||
const linterArgs = this.linterArgsMap.get(langID);
|
|
||||||
|
|
||||||
if (linterArgs === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const args = [filePath, ...linterArgs];
|
|
||||||
const executor = this.executableInvokeNameMap.get(langID);
|
|
||||||
if (executor !== undefined) {
|
|
||||||
const { stderr } = await easyExec(executor, args);
|
|
||||||
if (stderr.length > 0) {
|
|
||||||
const diagnostics = this.provideDiagnostics(document, stderr);
|
|
||||||
this.diagnostic.set(document.uri, diagnostics);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LinterOutput.report('verilator linter is not available, please check prj.verilator.install.path in your setting', {
|
|
||||||
level: ReportType.Error,
|
|
||||||
notify: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async remove(uri: vscode.Uri) {
|
|
||||||
this.diagnostic.delete(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param document
|
|
||||||
* @param stdout stdout from xvlog
|
|
||||||
* @returns { vscode.Diagnostic[] } linter info
|
|
||||||
*/
|
|
||||||
private provideDiagnostics(document: vscode.TextDocument, stderr: string): vscode.Diagnostic[] {
|
|
||||||
const diagnostics = [];
|
|
||||||
for (let line of stderr.split(/\r?\n/g)) {
|
|
||||||
if (!line.startsWith('%')) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
line = line.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tokens = line.split(':');
|
|
||||||
if (tokens.length < 3) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const header = tokens[0].toLowerCase();
|
|
||||||
const fileName = tokens[1];
|
|
||||||
const lineNo = parseInt(tokens[2]) - 1;
|
|
||||||
const characterNo = parseInt(tokens[3]) - 1;
|
|
||||||
const syntaxInfo = tokens[4];
|
|
||||||
|
|
||||||
if (header.startsWith('warning')) {
|
|
||||||
const range = this.makeCorrectRange(document, lineNo, characterNo);
|
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Warning);
|
|
||||||
diagnostics.push(diag);
|
|
||||||
} else if (header.startsWith('error')) {
|
|
||||||
const range = this.makeCorrectRange(document, lineNo, characterNo);
|
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
|
||||||
diagnostics.push(diag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diagnostics;
|
|
||||||
}
|
|
||||||
|
|
||||||
private makeCorrectRange(document: vscode.TextDocument, line: number, character: number): vscode.Range {
|
|
||||||
const startPosition = new vscode.Position(line, character);
|
|
||||||
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
|
||||||
if (wordRange) {
|
|
||||||
return wordRange;
|
|
||||||
} else {
|
|
||||||
return new vscode.Range(startPosition, startPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getExecutableFilePath(langID: HdlLangID): string | Path | undefined {
|
|
||||||
// verilator install path stored in prj.verilator.install.path
|
|
||||||
const verilatorConfig = vscode.workspace.getConfiguration('digital-ide.prj.verilator');
|
|
||||||
const verilatorInstallPath = verilatorConfig.get('install.path', '');
|
|
||||||
const executorName = this.executableFileMap.get(langID);
|
|
||||||
if (executorName === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. vlog.exe in windows, vlog in linux
|
|
||||||
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.exe' : executorName;
|
|
||||||
|
|
||||||
if (verilatorInstallPath.trim() === '' || !fs.existsSync(verilatorInstallPath)) {
|
|
||||||
LinterOutput.report(`User's verilator Install Path ${verilatorInstallPath}, which is invalid. Use ${executorName} in default.`, {
|
|
||||||
level: ReportType.Warn
|
|
||||||
});
|
|
||||||
LinterOutput.report('If you have doubts, check prj.verilator.install.path in setting', {
|
|
||||||
level: ReportType.Warn
|
|
||||||
});
|
|
||||||
return executorName;
|
|
||||||
} else {
|
|
||||||
LinterOutput.report(`User's verilator Install Path ${verilatorInstallPath}, which is invalid`);
|
|
||||||
|
|
||||||
const executorPath = hdlPath.join(
|
|
||||||
hdlPath.toSlash(verilatorInstallPath),
|
|
||||||
fullExecutorName
|
|
||||||
);
|
|
||||||
// prevent path like C://stupid name/xxx/xxx/bin
|
|
||||||
// blank space
|
|
||||||
const safeExecutorPath = '"' + executorPath + '"';
|
|
||||||
return safeExecutorPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async setExecutableFilePath(executorPath: string | Path | undefined, langID: HdlLangID): Promise<boolean> {
|
|
||||||
if (executorPath === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { stderr } = await easyExec(executorPath, []);
|
|
||||||
if (stderr.length === 0) {
|
|
||||||
this.executableInvokeNameMap.set(langID, executorPath);
|
|
||||||
LinterOutput.report(`success to verify ${executorPath}, linter from verilator is ready to go!`, {
|
|
||||||
level: ReportType.Launch
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
this.executableInvokeNameMap.set(langID, undefined);
|
|
||||||
console.log(stderr);
|
|
||||||
|
|
||||||
LinterOutput.report(`Fail to execute ${executorPath}! Reason: ${stderr}`, {
|
|
||||||
level: ReportType.Error,
|
|
||||||
notify: true
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async initialise(langID: HdlLangID): Promise<boolean> {
|
|
||||||
const executorPath = this.getExecutableFilePath(langID);
|
|
||||||
return this.setExecutableFilePath(executorPath, langID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const verilatorLinter = new VerilatorLinter();
|
|
||||||
|
|
||||||
export {
|
|
||||||
verilatorLinter,
|
|
||||||
VerilatorLinter
|
|
||||||
};
|
|
@ -1,198 +0,0 @@
|
|||||||
import * as vscode from "vscode";
|
|
||||||
import * as fs from 'fs';
|
|
||||||
|
|
||||||
import { LinterOutput, ReportType, opeParam } from "../../../global";
|
|
||||||
import { hdlFile, hdlPath } from "../../../hdlFs";
|
|
||||||
import { easyExec } from "../../../global/util";
|
|
||||||
import { HdlLangID } from "../../../global/enum";
|
|
||||||
|
|
||||||
type Path = string;
|
|
||||||
|
|
||||||
class VivadoLinter {
|
|
||||||
diagnostic: vscode.DiagnosticCollection;
|
|
||||||
executableFileMap: Map<HdlLangID, string | undefined> = new Map<HdlLangID, string>();
|
|
||||||
executableInvokeNameMap: Map<HdlLangID, string | undefined> = new Map<HdlLangID, string>();
|
|
||||||
linterArgsMap: Map<HdlLangID, string[]> = new Map<HdlLangID, string[]>();
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.diagnostic = vscode.languages.createDiagnosticCollection();
|
|
||||||
|
|
||||||
// configure map for executable file name
|
|
||||||
this.executableFileMap.set(HdlLangID.Verilog, 'xvlog');
|
|
||||||
this.executableFileMap.set(HdlLangID.Vhdl, 'xvhdl');
|
|
||||||
this.executableFileMap.set(HdlLangID.SystemVerilog, 'xvlog');
|
|
||||||
this.executableFileMap.set(HdlLangID.Unknown, undefined);
|
|
||||||
|
|
||||||
// configure map for argruments when lintering
|
|
||||||
this.linterArgsMap.set(HdlLangID.Verilog, ['--nolog']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.Vhdl, ['--nolog']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.SystemVerilog, ['--sv', '--nolog']);
|
|
||||||
this.linterArgsMap.set(HdlLangID.Unknown, []);
|
|
||||||
|
|
||||||
// this.initialise(HdlLangID.Verilog);
|
|
||||||
// this.initialise(HdlLangID.Vhdl);
|
|
||||||
// this.initialise(HdlLangID.SystemVerilog);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async lint(document: vscode.TextDocument) {
|
|
||||||
const filePath = hdlPath.toSlash(document.fileName);
|
|
||||||
const langID = hdlFile.getLanguageId(filePath);
|
|
||||||
|
|
||||||
// acquire install path
|
|
||||||
const linterArgs = this.linterArgsMap.get(langID);
|
|
||||||
if (linterArgs === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const args = [filePath, ...linterArgs];
|
|
||||||
const executor = this.executableInvokeNameMap.get(langID);
|
|
||||||
if (executor !== undefined) {
|
|
||||||
const { stdout } = await easyExec(executor, args);
|
|
||||||
if (stdout.length > 0) {
|
|
||||||
const diagnostics = this.provideDiagnostics(document, stdout);
|
|
||||||
this.diagnostic.set(document.uri, diagnostics);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LinterOutput.report('vivado linter is not available, please check prj.vivado.install.path in your setting', {
|
|
||||||
level: ReportType.Error,
|
|
||||||
notify: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async remove(uri: vscode.Uri) {
|
|
||||||
this.diagnostic.delete(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param document
|
|
||||||
* @param stdout stdout from xvlog
|
|
||||||
* @returns { vscode.Diagnostic[] } linter info
|
|
||||||
*/
|
|
||||||
private provideDiagnostics(document: vscode.TextDocument, stdout: string): vscode.Diagnostic[] {
|
|
||||||
const diagnostics = [];
|
|
||||||
for (const line of stdout.split(/\r?\n/g)) {
|
|
||||||
const tokens = line.split(/:?\s*(?:\[|\])\s*/);
|
|
||||||
const headerInfo = tokens[0];
|
|
||||||
// const standardInfo = tokens[1];
|
|
||||||
const syntaxInfo = tokens[2];
|
|
||||||
const parsedPath = tokens[3];
|
|
||||||
if (headerInfo === 'ERROR') {
|
|
||||||
const errorInfos = parsedPath.split(':');
|
|
||||||
const errorLine = Math.max(parseInt(errorInfos[errorInfos.length - 1]) - 1, 0);
|
|
||||||
LinterOutput.report(`<xvlog linter> line: ${errorLine}, info: ${syntaxInfo}`, {
|
|
||||||
level: ReportType.Run
|
|
||||||
});
|
|
||||||
|
|
||||||
const range = this.makeCorrectRange(document, errorLine, syntaxInfo);
|
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
|
||||||
diagnostics.push(diag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diagnostics;
|
|
||||||
}
|
|
||||||
|
|
||||||
private makeCorrectRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
|
||||||
// extract all the words like 'adawwd' in a syntax info
|
|
||||||
const singleQuoteWords = syntaxInfo.match(/'([^']*)'/g);
|
|
||||||
if (singleQuoteWords && singleQuoteWords.length > 0) {
|
|
||||||
const targetWord = singleQuoteWords.map(val => val.replace(/'/g, ''))[0];
|
|
||||||
// find range of target word
|
|
||||||
const textLine = document.lineAt(line);
|
|
||||||
const text = textLine.text;
|
|
||||||
const startCharacter = text.indexOf(targetWord);
|
|
||||||
if (startCharacter > -1) {
|
|
||||||
const endCharacter = startCharacter + targetWord.length;
|
|
||||||
const range = new vscode.Range(
|
|
||||||
new vscode.Position(line, startCharacter),
|
|
||||||
new vscode.Position(line, endCharacter)
|
|
||||||
);
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// else target the first word in the line
|
|
||||||
return this.makeCommonRange(document, line, syntaxInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private makeCommonRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
|
||||||
const startPosition = new vscode.Position(line, 0);
|
|
||||||
|
|
||||||
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
|
||||||
if (wordRange) {
|
|
||||||
return wordRange;
|
|
||||||
} else {
|
|
||||||
return new vscode.Range(startPosition, startPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getExecutableFilePath(langID: HdlLangID): string | Path | undefined {
|
|
||||||
// vivado install path stored in prj.vivado.install.path
|
|
||||||
const vivadoConfig = vscode.workspace.getConfiguration('digital-ide.prj.vivado');
|
|
||||||
const vivadoInstallPath = vivadoConfig.get('install.path', '');
|
|
||||||
const executorName = this.executableFileMap.get(langID);
|
|
||||||
if (executorName === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. xvlog.bat in windows, xvlog in linux
|
|
||||||
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.bat' : executorName;
|
|
||||||
|
|
||||||
if (vivadoInstallPath.trim() === '' || !fs.existsSync(vivadoInstallPath)) {
|
|
||||||
LinterOutput.report(`User's Vivado Install Path "${vivadoInstallPath}", which is invalid. Use ${executorName} in default.`, {
|
|
||||||
level: ReportType.Warn
|
|
||||||
});
|
|
||||||
LinterOutput.report('If you have doubts, check prj.vivado.install.path in setting', {
|
|
||||||
level: ReportType.Warn
|
|
||||||
});
|
|
||||||
|
|
||||||
return executorName;
|
|
||||||
} else {
|
|
||||||
LinterOutput.report(`User's Vivado Install Path "${vivadoInstallPath}", which is invalid`);
|
|
||||||
|
|
||||||
const executorPath = hdlPath.join(
|
|
||||||
hdlPath.toSlash(vivadoInstallPath),
|
|
||||||
fullExecutorName
|
|
||||||
);
|
|
||||||
// prevent path like C://stupid name/xxx/xxx/bin
|
|
||||||
// blank space
|
|
||||||
const safeExecutorPath = '"' + executorPath + '"';
|
|
||||||
return safeExecutorPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async setExecutableFilePath(executorPath: string | Path | undefined, langID: HdlLangID): Promise<boolean> {
|
|
||||||
if (executorPath === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { stderr } = await easyExec(executorPath, []);
|
|
||||||
if (stderr.length === 0) {
|
|
||||||
this.executableInvokeNameMap.set(langID, executorPath);
|
|
||||||
LinterOutput.report(`success to verify ${executorPath}, linter from vivado is ready to go!`, {
|
|
||||||
level: ReportType.Launch
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
this.executableInvokeNameMap.set(langID, undefined);
|
|
||||||
LinterOutput.report(`Fail to execute ${executorPath}! Reason: ${stderr}`, {
|
|
||||||
level: ReportType.Error,
|
|
||||||
notify: true
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async initialise(langID: HdlLangID): Promise<boolean> {
|
|
||||||
const executorPath = this.getExecutableFilePath(langID);
|
|
||||||
return await this.setExecutableFilePath(executorPath, langID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const vivadoLinter = new VivadoLinter();
|
|
||||||
|
|
||||||
export {
|
|
||||||
vivadoLinter,
|
|
||||||
VivadoLinter
|
|
||||||
};
|
|
@ -29,7 +29,7 @@ export const DoFastRequestType = new RequestType<IDoFastParam, Fast, void
|
|||||||
export const UpdateConfigurationType = new RequestType<IUpdateConfigurationParam, void, void>('api/update-configuration');
|
export const UpdateConfigurationType = new RequestType<IUpdateConfigurationParam, void, void>('api/update-configuration');
|
||||||
export const DoPrimitivesJudgeType = new RequestType<IDoPrimitivesJudgeParam, boolean, void>('api/do-primitives-judge');
|
export const DoPrimitivesJudgeType = new RequestType<IDoPrimitivesJudgeParam, boolean, void>('api/do-primitives-judge');
|
||||||
export const SyncFastRequestType = new RequestType<ISyncFastParam, Fast, void>('api/sync-fast');
|
export const SyncFastRequestType = new RequestType<ISyncFastParam, Fast, void>('api/sync-fast');
|
||||||
export const LinterStatusRequestType = new RequestType<ILinterStatusRequestType, LinterToolStatus, void>('api/linter-status');
|
export const LinterStatusRequestType = new RequestType<ILinterStatusParam, LinterToolStatus, void>('api/linter-status');
|
||||||
|
|
||||||
export interface ITextDocumentItem {
|
export interface ITextDocumentItem {
|
||||||
uri: vscode.Uri,
|
uri: vscode.Uri,
|
||||||
@ -57,7 +57,7 @@ export interface IUpdateConfigurationParam {
|
|||||||
configType: string
|
configType: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILinterStatusRequestType {
|
export interface ILinterStatusParam {
|
||||||
languageId: string,
|
languageId: string,
|
||||||
linterName: string,
|
linterName: string,
|
||||||
linterPath: string
|
linterPath: string
|
||||||
|
@ -332,7 +332,7 @@ class HdlParam {
|
|||||||
const increment = Math.floor(p.id / fileNum * 100);
|
const increment = Math.floor(p.id / fileNum * 100);
|
||||||
await p.promise;
|
await p.promise;
|
||||||
// console.log("handle id " + p.id + ' increment: ' + increment);
|
// console.log("handle id " + p.id + ' increment: ' + increment);
|
||||||
progress?.report({ message: reportTitle + ` ${p.id}/${fileNum}`, increment });
|
progress.report({ message: reportTitle + ` ${p.id}/${fileNum}`, increment });
|
||||||
}
|
}
|
||||||
pools.length = 0;
|
pools.length = 0;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import * as assert from 'assert';
|
|||||||
import { prjManage } from './prj';
|
import { prjManage } from './prj';
|
||||||
import { pickLibrary } from './libPick';
|
import { pickLibrary } from './libPick';
|
||||||
|
|
||||||
function registerManagerCommands(context: vscode.ExtensionContext) {
|
export function registerManagerCommands(context: vscode.ExtensionContext) {
|
||||||
// make ps and ps have been prepared
|
// make ps and ps have been prepared
|
||||||
assert(prjManage.pl, 'pl is undefined');
|
assert(prjManage.pl, 'pl is undefined');
|
||||||
// assert(prjManage.ps, 'ps is undefined');
|
// assert(prjManage.ps, 'ps is undefined');
|
||||||
@ -45,6 +45,5 @@ function registerManagerCommands(context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
prjManage,
|
prjManage
|
||||||
registerManagerCommands
|
|
||||||
};
|
};
|
@ -16,6 +16,7 @@ import { t } from '../i18n';
|
|||||||
import { PpyAction } from '../monitor/propery';
|
import { PpyAction } from '../monitor/propery';
|
||||||
import { refreshArchTree } from '../function/treeView';
|
import { refreshArchTree } from '../function/treeView';
|
||||||
import * as lspClient from '../function/lsp-client';
|
import * as lspClient from '../function/lsp-client';
|
||||||
|
import { refreshWorkspaceDiagonastics } from '../function/lsp/linter/manager';
|
||||||
|
|
||||||
|
|
||||||
interface RefreshPrjConfig {
|
interface RefreshPrjConfig {
|
||||||
@ -211,6 +212,8 @@ class PrjManage {
|
|||||||
if (countTimeCost) {
|
if (countTimeCost) {
|
||||||
console.timeLog('launch');
|
console.timeLog('launch');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return hdlFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async refreshPrjFolder(config?: RefreshPrjConfig) {
|
public async refreshPrjFolder(config?: RefreshPrjConfig) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user