finish left parts 1

This commit is contained in:
锦恢 2023-11-29 01:22:05 +08:00
parent e504d0450e
commit ea1a70e8aa
40 changed files with 871 additions and 231 deletions

1
.gitignore vendored
View File

@ -5,7 +5,6 @@ script/__pycache__
.vscode-test/
*.vsix
parser_stuck.v
**/*.wasm
out-js/
*.pyc
*.pyd

View File

@ -16,6 +16,7 @@ Change
- 将插件的工作状态显示在 vscode 下侧的状态栏上,利于用户了解目前的设置状态
- 状态栏右下角现在可以看到目前选择的linter以及是否正常工作了
- 优化项目配置目录
- 优化自动补全的性能
Feature
- 增加对 XDCTCL 等脚本的 LSP 支持

View File

@ -44,6 +44,11 @@
"default": true,
"description": "show the welcome text in Digital-IDE"
},
"digital-ide.dont-show-again.propose.issue": {
"type": "boolean",
"default": false,
"description": "show the welcome text in Digital-IDE"
},
"digital-ide.lib.custom.path": {
"type": "string",
"default": "",

Binary file not shown.

View File

@ -21,6 +21,7 @@ interface All {
error: Error[]
}
export function callParser(path: AbsPath, func: number): Promise<any | undefined>;
export function vlogFast(path: AbsPath): Promise<Fast | undefined>;
export function vlogAll(path: AbsPath): Promise<All | undefined>;
export function vhdlFast(path: AbsPath): Promise<Fast | undefined>;

View File

@ -1,4 +1,5 @@
const vscode = require('vscode');
const fs = require('fs');
const hdlParser = require('./parser');
@ -49,14 +50,21 @@ async function callParser(path, func) {
console.log(path, debug);
return JSON.parse(res);
} catch (error) {
console.log(`errors happen when call wasm, path: ${path}, errors: ${error}`);
console.log(`errors happen when call wasm, path: ${path}, errors: ${error}, input params: (${path}, ${func})`);
const dsaSetting = vscode.workspace.getConfiguration('digital-ide.dont-show-again');
if (dsaSetting.get('propose.issue', false) === true) {
return undefined;
}
const res = await vscode.window.showErrorMessage(
'Errors happen when parsing ' + path + '. Just propose a valuable issue in our github repo 😊',
`Errors happen when parsing ${path}. Error: "${error}". Just propose a valuable issue in our github repo 😊`,
{ title: 'Go and Propose!', value: true },
{ title: 'Refuse', value: false }
{ title: "Don't Show Again", value: false }
);
if (res && res.value) {
if (res && res.value === true) {
vscode.env.openExternal(vscode.Uri.parse(githubIssueUrl));
} else if (res && res.value === false) {
dsaSetting.update('propose.issue', true);
}
return undefined;
@ -95,5 +103,6 @@ module.exports = {
vhdlAll,
svFast,
svAll,
extensionUrl
extensionUrl,
callParser
};

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

10
script/test/callParser.js Normal file
View File

@ -0,0 +1,10 @@
const { vlogFast, callParser } = require('../../resources/hdlParser');
const testFile = 'c:/Users/11934/Project/Digital-IDE/Digital-Test/user/src/netlist_test.v';
(async () => {
const fast = await callParser(testFile, 5);
console.log(fast);
const all = await callParser(testFile, 6);
console.log(all);
})();

8
script/test/vhdlAll.js Normal file
View File

@ -0,0 +1,8 @@
const { vhdlAll } = require('../../resources/hdlParser');
const testFile = '../Digital-Test/Verilog/dependence_test/test.vhd';
(async () => {
const fast = await vhdlAll(testFile);
console.log(JSON.stringify(fast, null, ' '));
})();

8
script/test/vhdlFast.js Normal file
View File

@ -0,0 +1,8 @@
const { vhdlFast } = require('../../resources/hdlParser');
const testFile = '../Digital-Test/Verilog/dependence_test/test.vhd';
(async () => {
const fast = await vhdlFast(testFile);
console.log(JSON.stringify(fast, null, ' '));
})();

8
script/test/vlogAll.js Normal file
View File

@ -0,0 +1,8 @@
const { vlogAll } = require('../../resources/hdlParser');
const testFile = '../Digital-Test/user/src/netlist_test.v';
(async () => {
const all = await vlogAll(testFile);
console.log(JSON.stringify(all, null, ' '));
})();

View File

@ -1,6 +1,6 @@
const { vlogFast } = require('../../resources/hdlParser');
const { vlogFast, callParser } = require('../../resources/hdlParser');
const testFile = '../Digital-Test/Verilog/dependence_test/head_1.v';
const testFile = '../Digital-Test/user/src/netlist_test.v';
(async () => {
const fast = await vlogFast(testFile);

View File

@ -19,8 +19,7 @@ async function registerCommand(context: vscode.ExtensionContext) {
async function launch(context: vscode.ExtensionContext) {
vscode.window.withProgress({
await vscode.window.withProgress({
location: vscode.ProgressLocation.Window,
title: 'Initialization (Digtial-IDE)'
}, async () => {
@ -29,10 +28,10 @@ async function launch(context: vscode.ExtensionContext) {
hdlMonitor.start();
});
MainOutput.report('Digital-IDE has launched, Version: 0.3.2');
MainOutput.report('OS: ' + opeParam.os);
MainOutput.report('Digital-IDE has launched, Version: 0.3.2', ReportType.Launch);
MainOutput.report('OS: ' + opeParam.os, ReportType.Launch);
// console.log(hdlParam);
console.log(hdlParam);
// show welcome information (if first install)
const welcomeSetting = vscode.workspace.getConfiguration('digital-ide.welcome');

View File

@ -83,7 +83,9 @@ function registerLsp(context: vscode.ExtensionContext) {
// vhdl lsp
vscode.languages.registerDocumentSymbolProvider(vhdlSelector, lspDocSymbol.vhdlDocSymbolProvider);
vscode.languages.registerDefinitionProvider(vhdlSelector, lspDefinition.vhdlDefinitionProvider);
vscode.languages.registerHoverProvider(vhdlSelector, lspHover.vhdlHoverProvider);
vscode.languages.registerCompletionItemProvider(vhdlSelector, lspCompletion.vhdlCompletionProvider);

View File

@ -11,54 +11,28 @@ import { hdlPath } from '../../../hdlFs';
import { hdlSymbolStorage } from '../core';
class VhdlCompletionProvider implements vscode.CompletionItemProvider {
keywordItems: vscode.CompletionItem[] | undefined;
public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Promise<vscode.CompletionItem[] | vscode.CompletionList<vscode.CompletionItem> | null | undefined> {
// console.log('VhdlCompletionProvider');
try {
const filePath = hdlPath.toSlash(document.fileName);
// 1. provide keyword
const completions = this.makeKeywordItems(document, position);
completions.push(...this.makeCompilerKeywordItems(document, position));
completions.push(...this.makeSystemKeywordItems(document, position));
const symbolResult = await hdlSymbolStorage.getSymbol(filePath);
if (!symbolResult) {
return completions;
}
console.log('vhdl symbol result');
// locate at one module
const scopeSymbols = util.filterSymbolScope(position, symbolResult.content);
if (!scopeSymbols ||
!scopeSymbols.module ||
!hdlParam.hasHdlModule(filePath, scopeSymbols.module.name)) {
// MainOutput.report('Fail to get HdlModule ' + filePath + ' ' + scopeSymbols?.module.name, ReportType.Debug);
return completions;
const symbols = symbolResult.content;
for (const symbol of symbols) {
const kind = this.getCompletionItemKind(symbol.type);
const clItem = new vscode.CompletionItem(symbol.name, kind);
completions.push(clItem);
}
// find wrapper module
const currentModule = hdlParam.getHdlModule(filePath, scopeSymbols.module.name);
if (!currentModule) {
return completions;
}
// 3. provide modules
const suggestModulesPromise = this.provideModules(document, position, filePath, symbolResult.macro.includes);
// 4. provide params and ports of wrapper module
const suggestParamsPortsPromise = this.provideParamsPorts(currentModule);
// 5. provide nets
const suggestNetsPromise = this.provideNets(scopeSymbols.symbols);
// collect
completions.push(...await suggestModulesPromise);
completions.push(...await suggestParamsPortsPromise);
completions.push(...await suggestNetsPromise);
return completions;
} catch (err) {
@ -66,49 +40,43 @@ class VhdlCompletionProvider implements vscode.CompletionItemProvider {
}
}
private getCompletionItemKind(type: string): vscode.CompletionItemKind {
switch (type) {
case 'entity': return vscode.CompletionItemKind.Class; break;
case 'port': return vscode.CompletionItemKind.Variable; break;
default: return vscode.CompletionItemKind.Value; break;
}
}
private makeKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
const vhdlKeywordItem = [];
if (this.keywordItems !== undefined && this.keywordItems.length > 0) {
return this.keywordItems;
}
const vhdlKeywordItems: vscode.CompletionItem[] = [];
for (const keyword of vhdlKeyword.keys()) {
const clItem = this.makekeywordCompletionItem(keyword);
vhdlKeywordItem.push(clItem);
const clItem = this.makekeywordCompletionItem(keyword, 'vhdl keyword');
vhdlKeywordItems.push(clItem);
}
return vhdlKeywordItem;
}
private makeCompilerKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
const items = [];
const targetRange = document.getWordRangeAtPosition(position, /[`_0-9a-zA-Z]+/);
const targetWord = document.getText(targetRange);
const prefix = targetWord.startsWith('`') ? '' : '`';
for (const keyword of vhdlKeyword.compilerKeys()) {
const clItem = new vscode.CompletionItem(keyword, vscode.CompletionItemKind.Keyword);
clItem.insertText = new vscode.SnippetString(prefix + keyword);
clItem.detail = 'compiler directive';
items.push(clItem);
const clItem = this.makekeywordCompletionItem(keyword, 'IEEE lib function');
vhdlKeywordItems.push(clItem);
}
return items;
}
private makeSystemKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
const items = [];
for (const keyword of vhdlKeyword.systemKeys()) {
const clItem = new vscode.CompletionItem(keyword, vscode.CompletionItemKind.Method);
clItem.insertText = new vscode.SnippetString('\\$' + keyword + '($1);');
clItem.detail = 'system task';
items.push(clItem);
const clItem = this.makekeywordCompletionItem(keyword, 'vhdl keyword');
vhdlKeywordItems.push(clItem);
}
return items;
this.keywordItems = vhdlKeywordItems;
return vhdlKeywordItems;
}
private makekeywordCompletionItem(keyword: string): vscode.CompletionItem {
private makekeywordCompletionItem(keyword: string, detail: string): vscode.CompletionItem {
const clItem = new vscode.CompletionItem(keyword, vscode.CompletionItemKind.Keyword);
clItem.detail = 'keyword';
clItem.detail = detail;
switch (keyword) {
case 'begin': clItem.insertText = new vscode.SnippetString("begin$1\nend"); break;
case 'function': clItem.insertText = new vscode.SnippetString("function ${1:name}\n\nendfunction"); break;
case 'entity': clItem.insertText = new vscode.SnippetString("entity ${1:name} is\n\t${2:content}\nend entity;"); break;
case 'architecture': clItem.insertText = new vscode.SnippetString("architecture ${1:name} of ${2:entity} is\n\t${3:definition}\nbegin\n\t${4:content}\nend architecture;"); break;
default: break;
}
return clItem;

View File

@ -184,6 +184,7 @@ class VlogPositionPortProvider implements vscode.CompletionItemProvider {
}
class VlogCompletionProvider implements vscode.CompletionItemProvider {
keywordItems: vscode.CompletionItem[] | undefined;
public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Promise<vscode.CompletionItem[] | vscode.CompletionList<vscode.CompletionItem> | null | undefined> {
// console.log('VlogCompletionProvider');
@ -237,13 +238,16 @@ class VlogCompletionProvider implements vscode.CompletionItemProvider {
}
private makeKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
const vlogKeywordItem = [];
if (this.keywordItems !== undefined && this.keywordItems.length > 0) {
return this.keywordItems;
}
const vlogKeywordItems: vscode.CompletionItem[] = [];
for (const keyword of vlogKeyword.keys()) {
const clItem = this.makekeywordCompletionItem(keyword);
vlogKeywordItem.push(clItem);
vlogKeywordItems.push(clItem);
}
return vlogKeywordItem;
this.keywordItems = vlogKeywordItems;
return vlogKeywordItems;
}
private makeCompilerKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
@ -274,7 +278,7 @@ class VlogCompletionProvider implements vscode.CompletionItemProvider {
private makekeywordCompletionItem(keyword: string): vscode.CompletionItem {
const clItem = new vscode.CompletionItem(keyword, vscode.CompletionItemKind.Keyword);
clItem.detail = 'keyword';
clItem.detail = 'verilog keyword';
switch (keyword) {
case 'begin': clItem.insertText = new vscode.SnippetString("begin$1\nend"); break;

View File

@ -1,5 +1,7 @@
import { vlogDefinitionProvider } from './vlog';
import { vhdlDefinitionProvider } from './vhdl';
export {
vlogDefinitionProvider
vlogDefinitionProvider,
vhdlDefinitionProvider
};

View File

@ -0,0 +1,162 @@
import * as vscode from 'vscode';
import { hdlPath } from '../../../hdlFs';
import { hdlParam } from '../../../hdlParser';
import { All } from '../../../../resources/hdlParser';
import { vlogKeyword } from '../util/keyword';
import * as util from '../util';
import { MainOutput, ReportType } from '../../../global';
import { hdlSymbolStorage } from '../core';
class VhdlDefinitionProvider implements vscode.DefinitionProvider {
public async provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Location | vscode.LocationLink[] | null> {
// console.log('VhdlDefinitionProvider');
// get current words
const wordRange = document.getWordRangeAtPosition(position, /[`_0-9A-Za-z]+/);
if (!wordRange) {
return null;
}
const targetWord = document.getText(wordRange);
// check if need skip
if (this.needSkip(document, position, targetWord)) {
return null;
}
const filePath = document.fileName;
const vlogAll = await hdlSymbolStorage.getSymbol(filePath);
if (!vlogAll) {
return null;
} else {
const location = await this.makeDefinition(document, position, vlogAll, targetWord, wordRange);
return location;
}
}
private needSkip(document: vscode.TextDocument, position: vscode.Position, targetWord: string): boolean {
// check keyword
if (vlogKeyword.isKeyword(targetWord)) {
return true;
}
// TODO: check comment
return false;
}
private async makeDefinition(document: vscode.TextDocument, position: vscode.Position, all: All, targetWord: string, targetWordRange: vscode.Range): Promise<vscode.Location | vscode.LocationLink[] | null> {
const filePath = hdlPath.toSlash(document.fileName);
const lineText = document.lineAt(position).text;
// match `include
const includeResult = util.matchInclude(document, position, all.macro.includes);
if (includeResult) {
const absPath = hdlPath.rel2abs(filePath, includeResult.name);
const targetFile = vscode.Uri.file(absPath);
const targetPosition = new vscode.Position(0, 0);
const targetRange = new vscode.Range(targetPosition, targetPosition);
const originSelectionRange = document.getWordRangeAtPosition(position, /["\.\\\/_0-9A-Za-z]+/);
const link: vscode.LocationLink = { targetUri: targetFile, targetRange, originSelectionRange };
return [link];
}
// match macro
const macroResult = util.matchDefineMacro(position, targetWord, all.macro.defines);
if (macroResult) {
const targetRange = util.transformRange(macroResult.range, -1, -1);
const link: vscode.LocationLink = { targetUri: document.uri, targetRange: targetRange, originSelectionRange: targetWordRange };
return [link];
}
// locate at one module
const scopeSymbols = util.filterSymbolScope(position, all.content);
if (!scopeSymbols || !scopeSymbols.module) {
return null;
}
const currentModule = hdlParam.getHdlModule(filePath, scopeSymbols.module.name);
if (!currentModule) {
MainOutput.report('Fail to get HdlModule ' + filePath + ' ' + scopeSymbols.module.name, ReportType.Debug);
return null;
}
// match instance
const instResult = util.matchInstance(targetWord, currentModule);
if (instResult) {
const instModule = instResult.module;
if (!instModule || !instResult.instModPath) {
return null;
}
const targetFile = vscode.Uri.file(instResult.instModPath);
const targetRange = util.transformRange(instModule.range, -1, 0, 1);
const link: vscode.LocationLink = { targetUri: targetFile, targetRange };
return [link];
}
// match port or param definition (position input)
if (util.isPositionInput(lineText, position.character)) {
const currentInstResult = util.filterInstanceByPosition(position, scopeSymbols.symbols, currentModule);
if (!currentInstResult || !currentInstResult.instModPath) {
return null;
}
const instParamPromise = util.getInstParamByPosition(currentInstResult, position, targetWord);
const instPortPromise = util.getInstPortByPosition(currentInstResult, position, targetWord);
const instParam = await instParamPromise;
const instPort = await instPortPromise;
const instModPathUri = vscode.Uri.file(currentInstResult.instModPath);
if (instParam) {
const targetRange = util.transformRange(instParam.range, -1, 0);
const link: vscode.LocationLink = { targetUri: instModPathUri, targetRange };
return [link];
}
if (instPort) {
const targetRange = util.transformRange(instPort.range, -1, 0);
const link: vscode.LocationLink = { targetUri: instModPathUri, targetRange };
return [link];
}
return null;
}
// match params
const paramResult = util.matchParams(targetWord, currentModule);
if (paramResult) {
const targetRange = util.transformRange(paramResult.range, -1, 0);
const link: vscode.LocationLink = { targetUri: document.uri, targetRange };
return [link];
}
// match ports
const portResult = util.matchPorts(targetWord, currentModule);
if (portResult) {
const targetRange = util.transformRange(portResult.range, -1, 0);
const link: vscode.LocationLink = { targetUri: document.uri, targetRange };
return [link];
}
// match others
const normalResult = util.matchNormalSymbol(targetWord, scopeSymbols.symbols);
if (normalResult) {
const targetRange = util.transformRange(normalResult.range, -1, 0);
const link: vscode.LocationLink = { targetUri: document.uri, targetRange };
return [link];
}
return null;
}
}
const vhdlDefinitionProvider = new VhdlDefinitionProvider();
export {
vhdlDefinitionProvider
};

View File

@ -1,6 +1,8 @@
import { vlogDocSymbolProvider } from './vlog';
import { vhdlDocSymbolProvider } from './vhdl';
export {
vlogDocSymbolProvider
vlogDocSymbolProvider,
vhdlDocSymbolProvider
};

View File

@ -0,0 +1,64 @@
import * as vscode from 'vscode';
import { AllowNull } from '../../../global';
import { RawSymbol, Range } from '../../../hdlParser/common';
import { hdlSymbolStorage } from '../core';
import { positionAfterEqual } from '../util';
interface DocSymbolContainer {
docSymbol: AllowNull<vscode.DocumentSymbol>,
range: AllowNull<Range>
};
class VhdlDocSymbolProvider implements vscode.DocumentSymbolProvider {
public async provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.DocumentSymbol[]> {
const path = document.fileName;
const vhdlAll = await hdlSymbolStorage.getSymbol(path);
if (!vhdlAll || !vhdlAll.content) {
return [];
} else {
const symbols = vhdlAll.content;
const symbolInfos = this.makeDocumentSymbols(document, symbols);
return symbolInfos;
}
}
private makeDocumentSymbols(document: vscode.TextDocument, symbols: RawSymbol[]): vscode.DocumentSymbol[] {
const docSymbols: vscode.DocumentSymbol[] = [];
for (const symbol of symbols) {
const symbolStart = new vscode.Position(symbol.range.start.line - 1, symbol.range.start.character);
const symbolEnd = new vscode.Position(symbol.range.end.line - 1, symbol.range.end.character);
const symbolRange = new vscode.Range(symbolStart, symbolEnd);
if (symbol.type === 'entity') {
const docSymbol = new vscode.DocumentSymbol(symbol.name,
symbol.name,
vscode.SymbolKind.Interface,
symbolRange,
symbolRange);
docSymbols.push(docSymbol);
} else if (symbol.type === 'port') {
const parentEntity = docSymbols[docSymbols.length - 1];
const docSymbol = new vscode.DocumentSymbol(symbol.name,
symbol.name,
vscode.SymbolKind.Method,
symbolRange,
symbolRange);
parentEntity.children.push(docSymbol);
}
}
return docSymbols;
}
}
const vhdlDocSymbolProvider = new VhdlDocSymbolProvider();
export {
vhdlDocSymbolProvider
};

View File

@ -128,7 +128,7 @@ class VlogDocSymbolProvider implements vscode.DocumentSymbolProvider {
}
getSymbolKind(name: string): vscode.SymbolKind {
private getSymbolKind(name: string): vscode.SymbolKind {
if (name.indexOf('[') !== -1) {
return vscode.SymbolKind.Array;
}

View File

@ -1,5 +1,7 @@
import { vlogHoverProvider } from './vlog';
import { vhdlHoverProvider } from './vhdl';
export {
vlogHoverProvider
vlogHoverProvider,
vhdlHoverProvider
};

View File

@ -0,0 +1,204 @@
import * as vscode from 'vscode';
import { hdlPath } from '../../../hdlFs';
import { hdlParam } from '../../../hdlParser';
import { All } from '../../../../resources/hdlParser';
import { vlogKeyword } from '../util/keyword';
import * as util from '../util';
import { MainOutput, ReportType } from '../../../global';
import { HdlLangID } from '../../../global/enum';
import { hdlSymbolStorage } from '../core';
class VhdlHoverProvider implements vscode.HoverProvider {
public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Hover | null> {
// console.log('VhdlHoverProvider');
// get current words
const wordRange = document.getWordRangeAtPosition(position, /[`_0-9A-Za-z]+/);
if (!wordRange) {
return null;
}
const targetWord = document.getText(wordRange);
// check if need skip
if (this.needSkip(document, position, targetWord)) {
return null;
}
const filePath = document.fileName;
const vlogAll = await hdlSymbolStorage.getSymbol(filePath);
if (!vlogAll) {
return null;
} else {
const hover = await this.makeHover(document, position, vlogAll, targetWord, wordRange);
return hover;
}
}
private needSkip(document: vscode.TextDocument, position: vscode.Position, targetWord: string): boolean {
// check keyword
if (vlogKeyword.isKeyword(targetWord)) {
return true;
}
// TODO: check comment
return false;
}
private async makeHover(document: vscode.TextDocument, position: vscode.Position, all: All, targetWord: string, targetWordRange: vscode.Range): Promise<vscode.Hover | null> {
const lineText = document.lineAt(position).text;
const filePath = hdlPath.toSlash(document.fileName);
// total content rendered on the hover box
const content = new vscode.MarkdownString('', true);
// match `include
const includeResult = util.matchInclude(document, position, all.macro.includes);
if (includeResult) {
const absPath = hdlPath.rel2abs(filePath, includeResult.name);
content.appendCodeblock(`"${absPath}"`, HdlLangID.Verilog);
const targetRange = document.getWordRangeAtPosition(position, /[1-9a-zA-Z_\.]+/);
return new vscode.Hover(content, targetRange);
} else if (lineText.trim().startsWith('`include')) {
return null;
}
// match macro
const macroResult = util.matchDefineMacro(position, targetWord, all.macro.defines);
if (macroResult) {
const name = macroResult.name;
const value = macroResult.value;
content.appendCodeblock(`\`define ${name} ${value}`, HdlLangID.Verilog);
return new vscode.Hover(content, targetWordRange);
}
// locate at one module
const scopeSymbols = util.filterSymbolScope(position, all.content);
if (!scopeSymbols || !scopeSymbols.module || !hdlParam.hasHdlModule(filePath, scopeSymbols.module.name)) {
return null;
}
const currentModule = hdlParam.getHdlModule(filePath, scopeSymbols.module.name);
if (!currentModule) {
MainOutput.report('Fail to get HdlModule ' + filePath + ' ' + scopeSymbols.module.name, ReportType.Debug);
return null;
}
// match instance
const instResult = util.matchInstance(targetWord, currentModule);
if (instResult) {
const instModule = instResult.module;
if (!instModule || !instResult.instModPath) {
content.appendMarkdown('cannot find the definition of the module');
return new vscode.Hover(content);
}
await util.makeVlogHoverContent(content, instModule);
return new vscode.Hover(content);
}
// match port or param definition (position input)
/** for example, when you hover the ".clk" below, the branch will be entered
template u_template(
//input
.clk ( clk ),
);
*
*/
if (util.isPositionInput(lineText, position.character)) {
console.log('enter position input');
const currentInstResult = util.filterInstanceByPosition(position, scopeSymbols.symbols, currentModule);
if (!currentInstResult || !currentInstResult.instModPath) {
return null;
}
console.log(currentInstResult);
const instParamPromise = util.getInstParamByPosition(currentInstResult, position, targetWord);
const instPortPromise = util.getInstPortByPosition(currentInstResult, position, targetWord);
const instParam = await instParamPromise;
const instPort = await instPortPromise;
if (instParam) {
const paramComment = await util.searchCommentAround(currentInstResult.instModPath, instParam.range);
const paramDesc = util.makeParamDesc(instParam);
content.appendCodeblock(paramDesc, HdlLangID.Verilog);
if (paramComment) {
content.appendCodeblock(paramComment, HdlLangID.Verilog);
}
return new vscode.Hover(content);
}
if (instPort) {
const portComment = await util.searchCommentAround(currentInstResult.instModPath, instPort.range);
const portDesc = util.makePortDesc(instPort);
content.appendCodeblock(portDesc, HdlLangID.Verilog);
if (portComment) {
content.appendCodeblock(portComment, HdlLangID.Verilog);
}
return new vscode.Hover(content);
}
return null;
}
// match params
const paramResult = util.matchParams(targetWord, currentModule);
if (paramResult) {
const paramComment = await util.searchCommentAround(filePath, paramResult.range);
const paramDesc = util.makeParamDesc(paramResult);
content.appendCodeblock(paramDesc, HdlLangID.Verilog);
if (paramComment) {
content.appendCodeblock(paramComment, HdlLangID.Verilog);
}
return new vscode.Hover(content);
}
// match ports
const portResult = util.matchPorts(targetWord, currentModule);
if (portResult) {
const portComment = await util.searchCommentAround(filePath, portResult.range);
const portDesc = util.makePortDesc(portResult);
content.appendCodeblock(portDesc, HdlLangID.Verilog);
if (portComment) {
content.appendCodeblock(portComment, HdlLangID.Verilog);
}
return new vscode.Hover(content);
}
// match others
const normalResult = util.matchNormalSymbol(targetWord, scopeSymbols.symbols);
if (normalResult) {
const normalComment = await util.searchCommentAround(filePath, normalResult.range);
const normalDesc = util.makeNormalDesc(normalResult);
content.appendCodeblock(normalDesc, HdlLangID.Verilog);
if (normalComment) {
content.appendCodeblock(normalComment, HdlLangID.Verilog);
}
return new vscode.Hover(content);
}
// feature 1. number signed and unsigned number display
const numberResult = util.transferVlogNumber(lineText, position.character);
if (numberResult) {
const bits = targetWord.length - 1;
content.appendCodeblock(bits + "'" + targetWord, HdlLangID.Verilog);
content.appendMarkdown("`unsigned` " + numberResult.unsigned);
content.appendText('\n');
content.appendMarkdown("`signed` " + numberResult.signed);
}
return new vscode.Hover(content);
}
}
const vhdlHoverProvider = new VhdlHoverProvider();
export {
vhdlHoverProvider
};

View File

@ -7,6 +7,7 @@ import { HdlLangID } from '../../../global/enum';
import { vlogLinterManager } from './vlog';
import { vhdlLinterManager } from './vhdl';
import { easyExec } from '../../../global/util';
import { LspOutput } from '../../../global';
let _selectVlogLinter: string | null = null;
let _selectVhdlLinter: string | null = null;
@ -76,13 +77,20 @@ async function makeModelsimPickItem(langID: HdlLangID): Promise<LinterItem> {
async function pickVlogLinter() {
const pickWidget = vscode.window.createQuickPick<LinterItem>();
pickWidget.placeholder = 'select a linter for code diagnostic';
pickWidget.placeholder = 'select a linter for verilog code diagnostic';
pickWidget.canSelectMany = false;
pickWidget.items = [
await makeDefaultPickItem(),
await makeVivadoPickItem(HdlLangID.Verilog),
await makeModelsimPickItem(HdlLangID.Verilog)
];
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'Parsing local environment ...',
cancellable: true
}, async () => {
pickWidget.items = [
await makeDefaultPickItem(),
await makeVivadoPickItem(HdlLangID.Verilog),
await makeModelsimPickItem(HdlLangID.Verilog)
];
});
pickWidget.onDidChangeSelection(items => {
const selectedItem = items[0];
@ -101,7 +109,36 @@ async function pickVlogLinter() {
}
async function pickVhdlLinter() {
const pickWidget = vscode.window.createQuickPick<LinterItem>();
pickWidget.placeholder = 'select a linter for code diagnostic';
pickWidget.canSelectMany = false;
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'Parsing local environment ...',
cancellable: true
}, async () => {
pickWidget.items = [
await makeDefaultPickItem(),
await makeVivadoPickItem(HdlLangID.Vhdl),
await makeModelsimPickItem(HdlLangID.Vhdl)
];
});
pickWidget.onDidChangeSelection(items => {
const selectedItem = items[0];
_selectVlogLinter = selectedItem.name;
});
pickWidget.onDidAccept(() => {
if (_selectVlogLinter) {
const vlogLspConfig = vscode.workspace.getConfiguration('digital-ide.function.lsp.linter.vhdl');
vlogLspConfig.update('diagnostor', _selectVlogLinter);
pickWidget.hide();
}
});
pickWidget.show();
}

View File

@ -10,7 +10,7 @@ import { LspOutput, ReportType } from '../../../global';
class DefaultVlogLinter implements BaseLinter {
diagnostic: vscode.DiagnosticCollection;
constructor() {
this.diagnostic = vscode.languages.createDiagnosticCollection();
this.diagnostic = vscode.languages.createDiagnosticCollection('Digital-IDE Default Linter');
}
async lint(document: vscode.TextDocument): Promise<void> {
@ -28,8 +28,10 @@ class DefaultVlogLinter implements BaseLinter {
const diagnostics: vscode.Diagnostic[] = [];
if (all.error && all.error.length > 0) {
for (const hdlError of all.error) {
LspOutput.report(`<default linter> line: ${hdlError.range.line}, info: ${hdlError.message}`, ReportType.Run);
const syntaxInfo = hdlError.message.replace(/\\r\\n/g, '\n');
const range = this.makeCorrectRange(document, hdlError.range);
const diag = new vscode.Diagnostic(range, hdlError.message, hdlError.severity);
const diag = new vscode.Diagnostic(range, syntaxInfo, hdlError.severity);
diag.source = hdlError.source;
diagnostics.push(diag);
}
@ -78,7 +80,7 @@ class DefaultVlogLinter implements BaseLinter {
}
}
class DefaultVHDLLinter implements BaseLinter {
class DefaultVhdlLinter implements BaseLinter {
diagnostic: vscode.DiagnosticCollection;
constructor() {
this.diagnostic = vscode.languages.createDiagnosticCollection();
@ -99,6 +101,8 @@ class DefaultVHDLLinter implements BaseLinter {
const diagnostics: vscode.Diagnostic[] = [];
if (all.error && all.error.length > 0) {
for (const hdlError of all.error) {
LspOutput.report(`<default linter> line: ${hdlError.range.line}, info: ${hdlError.message}`, ReportType.Run);
const range = this.makeCorrectRange(document, hdlError.range);
const diag = new vscode.Diagnostic(range, hdlError.message, hdlError.severity);
diag.source = hdlError.source;
@ -150,11 +154,11 @@ class DefaultVHDLLinter implements BaseLinter {
}
const defaultVlogLinter = new DefaultVlogLinter();
const defaultVHDLLinter = new DefaultVHDLLinter();
const defaultVhdlLinter = new DefaultVhdlLinter();
export {
defaultVlogLinter,
defaultVHDLLinter,
defaultVhdlLinter,
DefaultVlogLinter,
DefaultVHDLLinter
DefaultVhdlLinter
};

View File

@ -2,38 +2,54 @@ 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 { defaultVhdlLinter } from './default';
import { modelsimLinter } from './modelsim';
import { vivadoLinter } from './vivado';
import { hdlFile, hdlPath } from '../../../hdlFs';
class VhdlLinterManager implements BaseManager {
currentLinter: BaseLinter | undefined;
activateList: Map<string, boolean> = new Map<string, boolean>();
activateLinterName: string;
statusBarItem: vscode.StatusBarItem;
initialized: boolean;
constructor() {
this.activateList.set('vivado', false);
this.activateList.set('modelsim', false);
this.activateList.set('default', false);
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.vhdl.linter.pick';
// when changing file, hide if langID is not vhdl
vscode.window.onDidChangeActiveTextEditor(editor => {
if (!editor) {
return;
}
const currentFileName = hdlPath.toSlash(editor.document.fileName);
if (hdlFile.isVhdlFile(currentFileName)) {
this.statusBarItem.show();
} else {
this.statusBarItem.hide();
}
});
// update when user's config is changed
vscode.workspace.onDidChangeConfiguration(() => {
const diagnostor = this.getUserDiagnostorSelection();
const lastDiagnostor = this.activateLinterName;
if (diagnostor !== lastDiagnostor) {
LspOutput.report(`<vhdl lsp manager> detect linter setting changes, switch ${lastDiagnostor} to ${diagnostor}.`, );
this.updateLinter();
}
this.updateLinter();
});
}
async initialise(): Promise<void> {
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.isVhdlFile(fileName)) {
@ -41,9 +57,18 @@ class VhdlLinterManager implements BaseManager {
}
}
LspOutput.report('<vhdl lsp manager> finish initialization of vhdl linter. Linter name: ' + this.activateLinterName, ReportType.Launch);
// hide it if current window is not vhdl
const editor = vscode.window.activeTextEditor;
if (editor && hdlFile.isVhdlFile(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);
}
@ -52,33 +77,63 @@ class VhdlLinterManager implements BaseManager {
}
public getUserDiagnostorSelection() {
const vlogLspConfig = vscode.workspace.getConfiguration('digital-ide.function.lsp.linter.vlog');
const diagnostor = vlogLspConfig.get('diagnostor', 'default');
const vhdlLspConfig = vscode.workspace.getConfiguration('digital-ide.function.lsp.linter.vhdl');
const diagnostor = vhdlLspConfig.get('diagnostor', 'xxx');
return diagnostor;
}
public async updateLinter(): Promise<boolean> {
const diagnostor = this.getUserDiagnostorSelection();
switch (diagnostor) {
case 'vivado': return this.activateVivado();
case 'modelsim': return this.activateModelsim();
case 'default': return this.activateDefault();
default: return this.activateDefault();
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(`<vhdl lsp manager> 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.isVhdlFile(fileName)) {
lastDiagnostor?.remove(doc.uri);
await this.lint(doc);
}
}
return launch;
}
public async activateVivado(): Promise<boolean> {
const selectedLinter = vivadoLinter;
let launch = true;
if (this.activateList.get('vivado') === false) {
launch = await selectedLinter.initialise(HdlLangID.Verilog);
this.activateList.set('vivado', true);
launch = await selectedLinter.initialise(HdlLangID.Vhdl);
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(vivado)';
LspOutput.report('<vhdl lsp manager> 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('<vhdl lsp manager> Fail to launch vivado linter', ReportType.Error);
}
this.currentLinter = selectedLinter;
this.activateLinterName = 'vivado';
this.statusBarItem.show();
return launch;
}
@ -86,29 +141,46 @@ class VhdlLinterManager implements BaseManager {
const selectedLinter = modelsimLinter;
let launch = true;
if (this.activateList.get('modelsim') === false) {
launch = await selectedLinter.initialise(HdlLangID.Verilog);
this.activateList.set('modelsim', true);
launch = await selectedLinter.initialise(HdlLangID.Vhdl);
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(modelsim)';
LspOutput.report('<vhdl lsp manager> 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('<vhdl lsp manager> Fail to launch modelsim linter', ReportType.Error);
}
this.currentLinter = selectedLinter;
this.activateLinterName = 'modelsim';
this.statusBarItem.show();
return launch;
}
public async activateDefault(): Promise<boolean> {
const selectedLinter = defaultVlogLinter;
const selectedLinter = defaultVhdlLinter;
let launch = true;
if (this.activateList.get('default') === false) {
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(default)';
this.activateList.set('default', true);
LspOutput.report('<vhdl lsp manager> 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('<vhdl lsp manager> Fail to launch default linter', ReportType.Error);
}
this.currentLinter = selectedLinter;
this.activateLinterName = 'default';
this.statusBarItem.show();
return launch;
}
}

View File

@ -171,7 +171,7 @@ class VivadoLinter implements BaseLinter {
public async initialise(langID: HdlLangID): Promise<boolean> {
const executorPath = this.getExecutableFilePath(langID);
return this.setExecutableFilePath(executorPath, langID);
return await this.setExecutableFilePath(executorPath, langID);
}
}

View File

@ -6,19 +6,16 @@ import { defaultVlogLinter } from './default';
import { modelsimLinter } from './modelsim';
import { vivadoLinter } from './vivado';
import { hdlFile, hdlPath } from '../../../hdlFs';
import { isVerilogFile } from '../../../hdlFs/file';
class VlogLinterManager implements BaseManager {
currentLinter: BaseLinter | undefined;
activateList: Map<string, boolean> = new Map<string, boolean>();
activateLinterName: string;
statusBarItem: vscode.StatusBarItem;
initialized: boolean;
constructor() {
this.activateList.set('vivado', false);
this.activateList.set('modelsim', false);
this.activateList.set('default', false);
this.activateLinterName = 'default';
this.initialized = false;
// make a status bar for rendering
this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
@ -31,7 +28,7 @@ class VlogLinterManager implements BaseManager {
}
const currentFileName = hdlPath.toSlash(editor.document.fileName);
if (isVerilogFile(currentFileName)) {
if (hdlFile.isVerilogFile(currentFileName)) {
this.statusBarItem.show();
} else {
this.statusBarItem.hide();
@ -40,21 +37,19 @@ class VlogLinterManager implements BaseManager {
// update when user's config is changed
vscode.workspace.onDidChangeConfiguration(() => {
const diagnostor = this.getUserDiagnostorSelection();
const lastDiagnostor = this.activateLinterName;
if (diagnostor !== lastDiagnostor) {
LspOutput.report(`<vlog lsp manager> detect linter setting changes, switch ${lastDiagnostor} to ${diagnostor}.`, );
this.updateLinter();
}
this.updateLinter();
});
}
async initialise(): Promise<void> {
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.isVerilogFile(fileName)) {
@ -62,9 +57,18 @@ class VlogLinterManager implements BaseManager {
}
}
LspOutput.report('<vlog lsp manager> finish initialization of vlog linter. Linter name: ' + this.activateLinterName, ReportType.Launch);
// hide it if current window is not verilog
const editor = vscode.window.activeTextEditor;
if (editor && hdlFile.isVerilogFile(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);
}
@ -74,38 +78,56 @@ class VlogLinterManager implements BaseManager {
public getUserDiagnostorSelection() {
const vlogLspConfig = vscode.workspace.getConfiguration('digital-ide.function.lsp.linter.vlog');
const diagnostor = vlogLspConfig.get('diagnostor', 'default');
const diagnostor = vlogLspConfig.get('diagnostor', 'xxx');
return diagnostor;
}
public async updateLinter() {
const diagnostor = this.getUserDiagnostorSelection();
switch (diagnostor) {
case 'vivado': return this.activateVivado();
case 'modelsim': return this.activateModelsim();
case 'default': return this.activateDefault();
default: return this.activateDefault();
public async updateLinter(): Promise<boolean> {
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(`<vlog lsp manager> 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.isVerilogFile(fileName)) {
lastDiagnostor?.remove(doc.uri);
await this.lint(doc);
}
}
return launch;
}
public async activateVivado(): Promise<boolean> {
const selectedLinter = vivadoLinter;
let launch = true;
if (this.activateList.get('vivado') === false) {
launch = await selectedLinter.initialise(HdlLangID.Verilog);
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(Vivado)';
launch = await selectedLinter.initialise(HdlLangID.Verilog);
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(vivado)';
this.activateList.set('vivado', true);
LspOutput.report('<vlog lsp manager> 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('<vlog lsp manager> 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('<vlog lsp manager> Fail to launch vivado linter', ReportType.Error);
}
LspOutput.report('<vlog lsp manager> Fail to launch vivado linter', ReportType.Error);
}
this.currentLinter = selectedLinter;
@ -119,22 +141,17 @@ class VlogLinterManager implements BaseManager {
const selectedLinter = modelsimLinter;
let launch = true;
if (this.activateList.get('modelsim') === false) {
launch = await selectedLinter.initialise(HdlLangID.Verilog);
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(modelsim)';
this.activateList.set('modelsim', true);
LspOutput.report('<vlog lsp manager> 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('<vlog lsp manager> Fail to launch modelsim linter', ReportType.Error);
}
launch = await selectedLinter.initialise(HdlLangID.Verilog);
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(modelsim)';
LspOutput.report('<vlog lsp manager> 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('<vlog lsp manager> Fail to launch modelsim linter', ReportType.Error);
}
this.currentLinter = selectedLinter;
@ -148,23 +165,22 @@ class VlogLinterManager implements BaseManager {
const selectedLinter = defaultVlogLinter;
let launch = true;
if (this.activateList.get('default') === false) {
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(default)';
if (launch) {
this.statusBarItem.text = '$(getting-started-beginner) Linter(default)';
this.activateList.set('default', true);
LspOutput.report('<vlog lsp manager> 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('<vlog lsp manager> 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('<vlog lsp manager> Fail to launch default linter', ReportType.Error);
}
LspOutput.report('<vlog lsp manager> Fail to launch default linter', ReportType.Error);
}
this.currentLinter = selectedLinter;
this.activateLinterName = 'default';
this.statusBarItem.show();
return launch;
}
}

View File

@ -1,6 +1,5 @@
import * as vscode from 'vscode';
class Keywords {
private keywords: Set<string>;
private compilerKeywords: string[]; // start with `
@ -76,7 +75,24 @@ const vlogKeyword = new Keywords([
);
// TODO : do vhdl and sv version
const vhdlKeyword = new Keywords([], [], []);
const vhdlKeyword = new Keywords(["abs", "configuration", "impure", "null", "rem", "type",
"access", "constant", "in", "of", "report", "unaffected", "after", "disconnect",
"inertial", "on", "return", "units", "alias", "downto", "inout", "open", "rol",
"until", "all", "else", "is", "or", "ror", "use", "and", "elsif", "label", "others",
"select", "variable", "architecture", "end", "library", "out", "severity", "wait", "array",
"entity", "linkage", "package", "signal", "when", "assert", "exit", "literal", "port", "shared",
"while", "attribute", "file", "loop", "postponed", "sla", "with", "begin", "for", "map", "procedure",
"sll", "xnor", "block", "function", "mod", "process", "sra", "xor", "body", "generate", "nand", "pure",
"srl", "buffer", "generic", "new", "range", "subtype", "bus", "group", "next", "record", "then", "case",
"guarded", "nor", "register", "to",
],
[
"std_logic", "std_ulogic", "std_logic_vector", "std_ulogic_vector", "signed", "unsigned", "complex", "complex_polar",
"boolean", "bit", "character", "severity_level", "integer", "real", "time", "delay_length", "now", "natural", "positive",
"string", "bit_vector", "file_open_kind", "file_open_status", "fs", "ps", "ns", "us", "ms", "sec", "min", "hr",
"severity_level", "note", "warning", "error", "failure", "line", "text", "side", "width", "input", "output"
],
[]);
const systemverilogKeyword = new Keywords([
"above", "disable", "idt", "notif1", "supply0", "abs", "discipline", "idtmod",

View File

@ -12,7 +12,7 @@ interface CommandDataItem {
cmd: string,
icon: string,
tip: string,
children: any[]
children: CommandDataItem[]
}
type CommandConfig = Record<string, {

View File

@ -14,6 +14,10 @@ async function openFileAtPosition(uri: vscode.Uri, line: number, character: numb
}
function openFileByUri(path: string, range: Range) {
if (range === undefined) {
vscode.window.showErrorMessage(`${path} not support jump yet`);
return;
}
if (hdlPath.exist(path)) {
const uri = vscode.Uri.file(path);
const start = range.start;

View File

@ -225,8 +225,8 @@ class ModuleTreeProvider implements vscode.TreeDataProvider<ModuleDataItem> {
icon: 'file',
type: instance.name,
name: instance.type,
range: instance.module ? instance.module.range : null,
path: instance.instModPath,
range: instance.range,
path: instance.parentMod.path,
parent: element
};
@ -257,6 +257,10 @@ class ModuleTreeProvider implements vscode.TreeDataProvider<ModuleDataItem> {
private judgeIcon(item: ModuleDataItem, instance: HdlInstance): string {
const workspacePath = opeParam.workspacePath;
if (instance.module === undefined) {
return 'File Error';
}
if (hdlPath.exist(item.path)) {
if (!item.path?.includes(workspacePath)) {
return 'remote';

View File

@ -1,3 +1,5 @@
import * as vscode from 'vscode';
import { AbsPath, opeParam } from '../global';
import { HdlLangID } from '../global/enum';
import { MainOutput, ReportType } from '../global/outputChannel';
@ -475,23 +477,52 @@ class HdlModule {
public createHdlInstance(rawHdlInstance: common.RawHdlInstance): HdlInstance {
const instModName = rawHdlInstance.type;
const searchResult = this.searchInstModPath(instModName);
const hdlInstance = new HdlInstance(rawHdlInstance.name,
rawHdlInstance.type,
searchResult.path,
searchResult.status,
rawHdlInstance.instparams,
rawHdlInstance.instports,
rawHdlInstance.range,
this);
if (!searchResult.path) {
hdlParam.addUnhandleInstance(hdlInstance);
this.addUnhandleInstance(hdlInstance);
if (this.languageId === HdlLangID.Verilog || this.languageId === HdlLangID.SystemVerilog) {
const searchResult = this.searchInstModPath(instModName);
const hdlInstance = new HdlInstance(rawHdlInstance.name,
rawHdlInstance.type,
searchResult.path,
searchResult.status,
rawHdlInstance.instparams,
rawHdlInstance.instports,
rawHdlInstance.range,
this);
if (!searchResult.path) {
hdlParam.addUnhandleInstance(hdlInstance);
this.addUnhandleInstance(hdlInstance);
}
if (this.nameToInstances) {
this.nameToInstances.set(rawHdlInstance.name, hdlInstance);
}
return hdlInstance;
} else if (this.languageId === HdlLangID.Vhdl) {
const hdlInstance = new HdlInstance(rawHdlInstance.name,
rawHdlInstance.type,
this.path,
common.InstModPathStatus.Current,
rawHdlInstance.instparams,
this.ports[0].range,
rawHdlInstance.range,
this);
hdlInstance.module = this;
if (this.nameToInstances) {
this.nameToInstances.set(rawHdlInstance.name, hdlInstance);
}
return hdlInstance;
} else {
vscode.window.showErrorMessage(`Unknown Language :${this.languageId} exist in our core program`);
const hdlInstance = new HdlInstance(rawHdlInstance.name,
rawHdlInstance.type,
this.path,
common.InstModPathStatus.Unknown,
rawHdlInstance.instparams,
this.ports[0].range,
rawHdlInstance.range,
this);
return hdlInstance;
}
if (this.nameToInstances) {
this.nameToInstances.set(rawHdlInstance.name, hdlInstance);
}
return hdlInstance;
}
public makeNameToInstances() {

View File

@ -155,7 +155,7 @@ class HdlAction extends BaseAction {
const fast = await HdlSymbol.fast(path);
if (!fast) {
vscode.window.showErrorMessage('error happen when parse ' + path + '\nFail to update');
// vscode.window.showErrorMessage('error happen when parse ' + path + '\nFail to update');
return;
}

View File

@ -1220,23 +1220,23 @@
"patterns": [
{
"match": "\\b(?i:boolean|bit|character|severity_level|integer|real|time|delay_length|now|natural|positive|string|bit_vector|file_open_kind|file_open_status|fs|ps|ns|us|ms|sec|min|hr|severity_level|note|warning|error|failure)\\b",
"name": "support.type.std.standard.vhdl"
"name": "support.function.type.std.standard.vhdl"
},
{
"match": "\\b(?i:line|text|side|width|input|output)\\b",
"name": "support.type.std.textio.vhdl"
"name": "support.function.type.std.textio.vhdl"
},
{
"match": "\\b(?i:std_logic|std_ulogic|std_logic_vector|std_ulogic_vector)\\b",
"name": "support.type.ieee.std_logic_1164.vhdl"
"name": "support.function.type.ieee.std_logic_1164.vhdl"
},
{
"match": "\\b(?i:signed|unsigned)\\b",
"name": "support.type.ieee.numeric_std.vhdl"
"name": "support.function.type.ieee.numeric_std.vhdl"
},
{
"match": "\\b(?i:complex|complex_polar)\\b",
"name": "support.type.ieee.math_complex.vhdl"
"name": "support.function.type.ieee.math_complex.vhdl"
}
]
},