diff --git a/resources/hdlParser/index.d.ts b/resources/hdlParser/index.d.ts index 2028a27..1c2b0f3 100644 --- a/resources/hdlParser/index.d.ts +++ b/resources/hdlParser/index.d.ts @@ -1,5 +1,5 @@ -import { RawHdlModule, Macro, RawSymbol } from '../../src/hdlParser/common'; -import { HdlLangID } from '../../src/global/enum'; +import type { RawHdlModule, Macro, RawSymbol, Error } from '../../src/hdlParser/common'; +import type { HdlLangID } from '../../src/global/enum'; type AbsPath = string; type RelPath = string; @@ -15,6 +15,7 @@ interface All { content: RawSymbol[] languageId: HdlLangID macro: Macro + error: Error[] } export function vlogFast(path: AbsPath): Promise; diff --git a/src/function/index.ts b/src/function/index.ts index 6880638..3570ea1 100644 --- a/src/function/index.ts +++ b/src/function/index.ts @@ -11,6 +11,7 @@ import * as lspHover from './lsp/hover'; import * as lspFormatter from '../../resources/formatter'; import * as lspTranslator from '../../resources/translator'; import * as lspDocSemantic from './lsp/docSemantic'; +import * as lspLinter from './lsp/linter'; import * as tool from './tool'; @@ -76,11 +77,15 @@ 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); + lspLinter.registerVlogLinterServer(); // vhdl lsp + + } + function registerToolCommands(context: vscode.ExtensionContext) { vscode.commands.registerCommand('digital-ide.lsp.tool.insertTextToUri', tool.insertTextToUri); vscode.commands.registerCommand('digital-ide.lsp.tool.transformOldPropertyFile', tool.transformOldPpy); diff --git a/src/function/lsp/linter/index.ts b/src/function/lsp/linter/index.ts new file mode 100644 index 0000000..5957ed0 --- /dev/null +++ b/src/function/lsp/linter/index.ts @@ -0,0 +1,5 @@ +import { registerVlogLinterServer } from './vlog'; + +export { + registerVlogLinterServer +}; \ No newline at end of file diff --git a/src/function/lsp/linter/vlog.ts b/src/function/lsp/linter/vlog.ts new file mode 100644 index 0000000..1a1a594 --- /dev/null +++ b/src/function/lsp/linter/vlog.ts @@ -0,0 +1,89 @@ +import * as vscode from 'vscode'; +import { All } from '../../../../resources/hdlParser'; +import { hdlParam, HdlSymbol } from '../../../hdlParser'; +import { Position, Range } from '../../../hdlParser/common'; + + +class VlogLinter { + diagnostic: vscode.DiagnosticCollection; + constructor() { + this.diagnostic = vscode.languages.createDiagnosticCollection(); + } + + async lint(document: vscode.TextDocument) { + const filePath = document.fileName; + const vlogAll = await HdlSymbol.all(filePath); + if (vlogAll) { + const diagnostics = this.provideDiagnostics(document, vlogAll); + this.diagnostic.set(document.uri, diagnostics); + } + } + + private provideDiagnostics(document: vscode.TextDocument, all: All): vscode.Diagnostic[] { + const diagnostics: vscode.Diagnostic[] = []; + if (all.error && all.error.length > 0) { + for (const hdlError of all.error) { + const range = this.makeCorrectRange(document, hdlError.range); + const diag = new vscode.Diagnostic(range, hdlError.message, hdlError.severity); + diag.source = hdlError.source; + diagnostics.push(diag); + } + } + console.log(diagnostics); + + return diagnostics; + } + + private makeCorrectRange(document: vscode.TextDocument, range: Position): vscode.Range { + range.line --; + if (range.character === 0 && range.line > 0) { + range.line --; + } + + while (range.line > 0) { + const lineContent = document.lineAt(range.line).text; + if (lineContent.trim().length > 0) { + break; + } else { + range.line --; + } + } + + const currentLine = document.lineAt(range.line).text; + 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]+/); + if (wordRange) { + return wordRange; + } else { + const errorEnd = new vscode.Position(range.line, range.character + 1); + const errorRange = new vscode.Range(position, errorEnd); + return errorRange; + } + } + + async remove(document: vscode.TextDocument) { + this.diagnostic.delete(document.uri); + } +} + +function registerVlogLinterServer() { + const linter = new VlogLinter(); + vscode.workspace.onDidOpenTextDocument(doc => { + linter.lint(doc); + }); + vscode.workspace.onDidSaveTextDocument(doc => { + linter.lint(doc); + }); + vscode.workspace.onDidCloseTextDocument(doc => { + linter.remove(doc); + }); +} + +export { + registerVlogLinterServer +}; \ No newline at end of file diff --git a/src/hdlParser/common.ts b/src/hdlParser/common.ts index 00d13af..d6b9b57 100644 --- a/src/hdlParser/common.ts +++ b/src/hdlParser/common.ts @@ -78,10 +78,12 @@ enum InstModPathStatus {Current, Include, Others, Unknown}; // }; interface Error { - severity: number + severity: vscode.DiagnosticSeverity message: string source: string - range: Range + range: Position + running_mode?: string + running_phase?: string }; interface DefineParam { diff --git a/src/test/user/src/hello.v b/src/test/user/src/hello.v index c96ec27..eaff86e 100644 --- a/src/test/user/src/hello.v +++ b/src/test/user/src/hello.v @@ -8,9 +8,5 @@ module mux2to1( ); - - - assign outp = sel == 1'b0 ? a : b; - endmodule