diff --git a/src/function/index.ts b/src/function/index.ts index a0bc302..caf6cd7 100644 --- a/src/function/index.ts +++ b/src/function/index.ts @@ -14,6 +14,7 @@ import * as lspDocSemantic from './lsp/docSemantic'; import * as lspLinter from './lsp/linter'; import * as tool from './tool'; +import * as lspCore from './lsp/core'; // special function import * as FSM from './fsm'; @@ -77,9 +78,10 @@ function registerLsp(context: vscode.ExtensionContext) { vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogPositionPortProvider, '.'); vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogCompletionProvider); vscode.languages.registerDocumentSemanticTokensProvider(vlogSelector, lspDocSemantic.vlogDocSenmanticProvider, lspDocSemantic.vlogLegend); - const vlogLinter = lspLinter.registerVlogLinterServer(); - lspLinter.firstLinter(vlogLinter); + lspLinter.vlogLinter.initialise(); + lspCore.vlogSymbolStorage.initialise(); + // vhdl lsp } diff --git a/src/function/lsp/completion/vlog.ts b/src/function/lsp/completion/vlog.ts index da87e71..7bd5752 100644 --- a/src/function/lsp/completion/vlog.ts +++ b/src/function/lsp/completion/vlog.ts @@ -3,15 +3,18 @@ import * as fs from 'fs'; import * as util from '../util'; import { hdlFile, hdlPath } from '../../../hdlFs'; -import { hdlParam, HdlSymbol } from '../../../hdlParser'; +import { hdlParam } from '../../../hdlParser'; import { AbsPath, MainOutput, RelPath, ReportType } from '../../../global'; import { Define, Include, RawSymbol } from '../../../hdlParser/common'; import { HdlInstance, HdlModule } from '../../../hdlParser/core'; import { vlogKeyword } from '../util/keyword'; import { instanceVlogCode } from '../../sim/instance'; +import { vlogSymbolStorage } from '../core'; class VlogIncludeCompletionProvider implements vscode.CompletionItemProvider { public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): vscode.ProviderResult> { + // console.log('VlogIncludeCompletionProvider'); + try { const items = this.provideIncludeFiles(document, position); return items; @@ -67,11 +70,14 @@ class VlogIncludeCompletionProvider implements vscode.CompletionItemProvider { class VlogMacroCompletionProvider implements vscode.CompletionItemProvider { public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Promise | null | undefined> { + // console.log('VlogMacroCompletionProvider'); + try { const targetWordRange = document.getWordRangeAtPosition(position, /[`_0-9a-zA-Z]+/); const targetWord = document.getText(targetWordRange); const filePath = document.fileName; - const symbolResult = await HdlSymbol.all(filePath); + + const symbolResult = await vlogSymbolStorage.getSymbol(filePath); if (!symbolResult) { return null; } @@ -102,10 +108,12 @@ class VlogMacroCompletionProvider implements vscode.CompletionItemProvider { class VlogPositionPortProvider implements vscode.CompletionItemProvider { public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Promise | null | undefined> { + // console.log('VlogPositionPortProvider'); + try { const suggestPositionPorts: vscode.CompletionItem[] = []; const filePath = hdlPath.toSlash(document.fileName); - const symbolResult = await HdlSymbol.all(filePath); + const symbolResult = await vlogSymbolStorage.getSymbol(filePath); if (!symbolResult) { return null; } @@ -173,6 +181,8 @@ class VlogPositionPortProvider implements vscode.CompletionItemProvider { class VlogCompletionProvider implements vscode.CompletionItemProvider { public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Promise | null | undefined> { + // console.log('VlogCompletionProvider'); + try { const filePath = hdlPath.toSlash(document.fileName); @@ -181,7 +191,7 @@ class VlogCompletionProvider implements vscode.CompletionItemProvider { completions.push(...this.makeCompilerKeywordItems(document, position)); completions.push(...this.makeSystemKeywordItems(document, position)); - const symbolResult = await HdlSymbol.all(filePath); + const symbolResult = await vlogSymbolStorage.getSymbol(filePath); if (!symbolResult) { return completions; } diff --git a/src/function/lsp/core/index.ts b/src/function/lsp/core/index.ts new file mode 100644 index 0000000..e1cb8c1 --- /dev/null +++ b/src/function/lsp/core/index.ts @@ -0,0 +1,5 @@ +import { vlogSymbolStorage } from './vlog'; + +export { + vlogSymbolStorage +}; \ No newline at end of file diff --git a/src/function/lsp/core/vlog.ts b/src/function/lsp/core/vlog.ts new file mode 100644 index 0000000..bc94308 --- /dev/null +++ b/src/function/lsp/core/vlog.ts @@ -0,0 +1,48 @@ +import * as vscode from 'vscode'; +import { All } from '../../../../resources/hdlParser'; +import { AbsPath } from '../../../global'; +import { hdlPath } from '../../../hdlFs'; +import { isVerilogFile } from '../../../hdlFs/file'; +import { HdlSymbol } from '../../../hdlParser'; + +type ThenableAll = Promise; + +class VlogSymbolStorage { + private symbolMap: Map; + constructor() { + this.symbolMap = new Map(); + } + + public async getSymbol(path: AbsPath): ThenableAll { + path = hdlPath.toSlash(path); + const all = await this.symbolMap.get(path); + return all; + } + + public async updateSymbol(path: AbsPath) { + path = hdlPath.toSlash(path); + const vlogAllPromise = HdlSymbol.all(path); + this.symbolMap.set(path, vlogAllPromise); + } + + public async deleteSymbol(path: AbsPath) { + path = hdlPath.toSlash(path); + this.symbolMap.delete(path); + } + + + public async initialise() { + for (const doc of vscode.workspace.textDocuments) { + if (isVerilogFile(doc.fileName)) { + // TODO : check performance + await this.updateSymbol(doc.fileName); + } + } + } +} + +const vlogSymbolStorage = new VlogSymbolStorage(); + +export { + vlogSymbolStorage +}; \ No newline at end of file diff --git a/src/function/lsp/definition/vlog.ts b/src/function/lsp/definition/vlog.ts index 4f3cda5..c5321b5 100644 --- a/src/function/lsp/definition/vlog.ts +++ b/src/function/lsp/definition/vlog.ts @@ -2,16 +2,18 @@ import * as vscode from 'vscode'; import * as vsctm from 'vscode-textmate'; import { hdlPath } from '../../../hdlFs'; -import { hdlParam, HdlSymbol } from '../../../hdlParser'; +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 { vlogSymbolStorage } from '../core'; class VlogDefinitionProvider implements vscode.DefinitionProvider { - public async provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { + // console.log('VlogDefinitionProvider'); + // get current words const wordRange = document.getWordRangeAtPosition(position, /[`_0-9A-Za-z]+/); if (!wordRange) { @@ -25,7 +27,7 @@ class VlogDefinitionProvider implements vscode.DefinitionProvider { } const filePath = document.fileName; - const vlogAll = await HdlSymbol.all(filePath); + const vlogAll = await vlogSymbolStorage.getSymbol(filePath); if (!vlogAll) { return null; } else { diff --git a/src/function/lsp/docSemantic/vlog.ts b/src/function/lsp/docSemantic/vlog.ts index 4ec96a5..3462660 100644 --- a/src/function/lsp/docSemantic/vlog.ts +++ b/src/function/lsp/docSemantic/vlog.ts @@ -1,15 +1,14 @@ import * as vscode from 'vscode'; -import { HdlSymbol } from '../../../hdlParser'; - const tokenTypes = ['class', 'interface', 'enum', 'function', 'variable']; const tokenModifiers = ['declaration', 'documentation']; const vlogLegend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers); class VlogDocSenmanticProvider implements vscode.DocumentSemanticTokensProvider { public async provideDocumentSemanticTokens(document: vscode.TextDocument, token: vscode.CancellationToken): Promise { - const tokensBuilder = new vscode.SemanticTokensBuilder(vlogLegend); - return tokensBuilder.build(); + // TODO : finish this + // const tokensBuilder = new vscode.SemanticTokensBuilder(vlogLegend); + return null; } } diff --git a/src/function/lsp/docSymbol/vlog.ts b/src/function/lsp/docSymbol/vlog.ts index 238eeed..534417f 100644 --- a/src/function/lsp/docSymbol/vlog.ts +++ b/src/function/lsp/docSymbol/vlog.ts @@ -1,8 +1,8 @@ import * as vscode from 'vscode'; import { AllowNull } from '../../../global'; -import { HdlSymbol } from '../../../hdlParser'; import { RawSymbol, Range } from '../../../hdlParser/common'; +import { vlogSymbolStorage } from '../core'; import { positionAfterEqual } from '../util'; @@ -13,8 +13,10 @@ interface DocSymbolContainer { class VlogDocSymbolProvider implements vscode.DocumentSymbolProvider { public async provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): Promise { + // console.log('VlogDocSymbolProvider'); + const path = document.fileName; - const vlogAll = await HdlSymbol.all(path); + const vlogAll = await vlogSymbolStorage.getSymbol(path); if (!vlogAll || !vlogAll.content) { return []; diff --git a/src/function/lsp/hover/vlog.ts b/src/function/lsp/hover/vlog.ts index 7a41892..62e0cc6 100644 --- a/src/function/lsp/hover/vlog.ts +++ b/src/function/lsp/hover/vlog.ts @@ -1,16 +1,19 @@ import * as vscode from 'vscode'; -import { hdlDir, hdlPath } from '../../../hdlFs'; -import { hdlParam, HdlSymbol } from '../../../hdlParser'; +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 { vlogSymbolStorage } from '../core'; class VlogHoverProvider implements vscode.HoverProvider { public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { + // console.log('VlogHoverProvider'); + // get current words const wordRange = document.getWordRangeAtPosition(position, /[`_0-9A-Za-z]+/); if (!wordRange) { @@ -24,7 +27,7 @@ class VlogHoverProvider implements vscode.HoverProvider { } const filePath = document.fileName; - const vlogAll = await HdlSymbol.all(filePath); + const vlogAll = await vlogSymbolStorage.getSymbol(filePath); if (!vlogAll) { return null; } else { diff --git a/src/function/lsp/linter/index.ts b/src/function/lsp/linter/index.ts index 0c2ad5c..cd93afe 100644 --- a/src/function/lsp/linter/index.ts +++ b/src/function/lsp/linter/index.ts @@ -1,6 +1,5 @@ -import { registerVlogLinterServer, firstLinter } from './vlog'; +import { vlogLinter } from './vlog'; export { - registerVlogLinterServer, - firstLinter + vlogLinter }; \ No newline at end of file diff --git a/src/function/lsp/linter/vlog.ts b/src/function/lsp/linter/vlog.ts index 7c0aefa..5ae17a0 100644 --- a/src/function/lsp/linter/vlog.ts +++ b/src/function/lsp/linter/vlog.ts @@ -1,8 +1,8 @@ import * as vscode from 'vscode'; import { All } from '../../../../resources/hdlParser'; -import { getLanguageId, isVerilogFile } from '../../../hdlFs/file'; -import { hdlParam, HdlSymbol } from '../../../hdlParser'; +import { isVerilogFile } from '../../../hdlFs/file'; import { Position, Range } from '../../../hdlParser/common'; +import { vlogSymbolStorage } from '../core'; class VlogLinter { @@ -13,7 +13,9 @@ class VlogLinter { async lint(document: vscode.TextDocument) { const filePath = document.fileName; - const vlogAll = await HdlSymbol.all(filePath); + const vlogAll = await vlogSymbolStorage.getSymbol(filePath); + console.log('lint all finish'); + if (vlogAll) { const diagnostics = this.provideDiagnostics(document, vlogAll); this.diagnostic.set(document.uri, diagnostics); @@ -29,9 +31,7 @@ class VlogLinter { diag.source = hdlError.source; diagnostics.push(diag); } - } - console.log(diagnostics); - + } return diagnostics; } @@ -54,7 +54,6 @@ class VlogLinter { if (range.character === 0 && currentLine.trim().length > 0) { range.character = currentLine.trimEnd().length; } - console.log(range); const position = new vscode.Position(range.line, range.character); const wordRange = document.getWordRangeAtPosition(position, /[`_0-9a-zA-Z]+/); @@ -70,37 +69,19 @@ class VlogLinter { async remove(document: vscode.TextDocument) { this.diagnostic.delete(document.uri); } -} -function registerVlogLinterServer(): VlogLinter { - const linter = new VlogLinter(); - vscode.workspace.onDidOpenTextDocument(doc => { - if (isVerilogFile(doc.fileName)) { - linter.lint(doc); - } - }); - vscode.workspace.onDidSaveTextDocument(doc => { - if (isVerilogFile(doc.fileName)) { - linter.lint(doc); - } - }); - vscode.workspace.onDidCloseTextDocument(doc => { - if (isVerilogFile(doc.fileName)) { - linter.remove(doc); - } - }); - return linter; -} - -async function firstLinter(linter: VlogLinter) { - for (const doc of vscode.workspace.textDocuments) { - if (isVerilogFile(doc.fileName)) { - linter.lint(doc); + public async initialise() { + for (const doc of vscode.workspace.textDocuments) { + if (isVerilogFile(doc.fileName)) { + // TODO : check performance + await this.lint(doc); + } } } } +const vlogLinter = new VlogLinter(); + export { - registerVlogLinterServer, - firstLinter + vlogLinter }; \ No newline at end of file diff --git a/src/monitor/event.ts b/src/monitor/event.ts index 001909a..2717801 100644 --- a/src/monitor/event.ts +++ b/src/monitor/event.ts @@ -13,6 +13,9 @@ import { prjManage } from '../manager'; import { libManage } from '../manager/lib'; import type { HdlMonitor } from './index'; import { ToolChainType } from '../global/enum'; +import { vlogSymbolStorage } from '../function/lsp/core'; +import { vlogLinter } from '../function/lsp/linter'; +import { isVerilogFile } from '../hdlFs/file'; enum Event { Add = 'add', // emit when add file @@ -70,6 +73,8 @@ class HdlAction extends BaseAction { path = hdlPath.toSlash(path); + this.updateLinter(path); + // check if it has been created if (hdlParam.hasHdlFile(path)) { MainOutput.report(' HdlFile ' + path + ' has been created', ReportType.Warn); @@ -91,6 +96,10 @@ class HdlAction extends BaseAction { hdlParam.deleteHdlFile(path); refreshArchTree(); } + + const uri = vscode.Uri.file(path); + const document = await vscode.workspace.openTextDocument(uri); + vlogLinter.remove(document); } async unlinkDir(path: string, m: HdlMonitor): Promise { @@ -105,8 +114,29 @@ class HdlAction extends BaseAction { async change(path: string, m: HdlMonitor): Promise { console.log('HdlAction change'); - path = hdlPath.toSlash(path); + + // TODO : check performance + await this.updateSymbolStorage(path); + await this.updateLinter(path); + + await this.updateHdlParam(path); + refreshArchTree(); + } + + async updateSymbolStorage(path: string) { + vlogSymbolStorage.updateSymbol(path); + } + + async updateLinter(path: string) { + if (isVerilogFile(path)) { + const uri = vscode.Uri.file(path); + const document = await vscode.workspace.openTextDocument(uri); + vlogLinter.lint(document); + } + } + + async updateHdlParam(path: string) { const moduleFile = hdlParam.getHdlFile(path); if (!moduleFile) { @@ -147,8 +177,6 @@ class HdlAction extends BaseAction { for (const moduleName of uncheckedModuleNames) { moduleFile.deleteHdlModule(moduleName); } - - refreshArchTree(); } } diff --git a/src/test/user/Hardware/src/clkdiv.v b/src/test/user/Hardware/src/clkdiv.v new file mode 100644 index 0000000..05a47c1 --- /dev/null +++ b/src/test/user/Hardware/src/clkdiv.v @@ -0,0 +1,29 @@ +module clkdiv( + input clk50, + input rst_n, + output reg clkout +); + reg [15:0] cnt; + always @(posedge clk50 or negedge rst_n) + begin + if(!rst_n) + begin + cnt <= 16'b0; + clkout <= 1'b0; + end + else if(cnt == 16'd162) + begin + clkout <= 1'b1; + cnt <= cnt + 16'd1; + end + else if(cnt == 16'd325) + begin + clkout <= 1'b0; + cnt <= 16'd0; + end + else + begin + cnt <= cnt + 16'd1; + end + end +endmodule \ No newline at end of file diff --git a/src/test/user/Hardware/src/hello.v b/src/test/user/Hardware/src/hello.v index c96ec27..9d67aa1 100644 --- a/src/test/user/Hardware/src/hello.v +++ b/src/test/user/Hardware/src/hello.v @@ -7,10 +7,7 @@ module mux2to1( output wire outp ); - - - - + assign outp = sel == 1'b0 ? a : b; endmodule