From a3746b99bd790f117dfdb607a6c1bb63b0e79936 Mon Sep 17 00:00:00 2001 From: James Yu Date: Sat, 26 Oct 2024 23:40:07 +0800 Subject: [PATCH] Fix #4449 Add a warning message when bibtex parser failed --- src/completion/completer/citation.ts | 5 ++--- src/core/commands.ts | 5 ++++- src/lint/bibtex-formatter.ts | 2 +- src/outline/structure/bibtex.ts | 2 +- src/parse/parser.ts | 20 ++++++++++++++++---- src/parse/parser/unified.ts | 9 +++++---- test/units/11_parser_tex.test.ts | 5 +++-- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/completion/completer/citation.ts b/src/completion/completer/citation.ts index 4ea1bff67..b54d1307a 100644 --- a/src/completion/completer/citation.ts +++ b/src/completion/completer/citation.ts @@ -1,5 +1,4 @@ import * as vscode from 'vscode' -import * as fs from 'fs' import { bibtexParser } from 'latex-utensils' import { lw } from '../../lw' import type { CitationField, CitationItem, CompletionArgs, CompletionItem, CompletionProvider } from '../../types' @@ -245,9 +244,9 @@ async function parseBibFile(fileName: string) { return } const newEntry: CitationItem[] = [] - const bibtex = fs.readFileSync(fileName).toString() + const bibtex = await lw.file.read(fileName) logger.log(`Parse BibTeX AST from ${fileName} .`) - const ast = await lw.parser.parse.bib(bibtex) + const ast = await lw.parser.parse.bib(vscode.Uri.file(fileName), bibtex ?? '') if (ast === undefined) { logger.log(`Parsed 0 bib entries from ${fileName}.`) lw.event.fire(lw.event.FileParsed, fileName) diff --git a/src/core/commands.ts b/src/core/commands.ts index 7f3a78d07..c3fa65d64 100644 --- a/src/core/commands.ts +++ b/src/core/commands.ts @@ -424,7 +424,10 @@ export async function devParseBib() { if (vscode.window.activeTextEditor === undefined) { return } - const ast = await lw.parser.parse.bib(vscode.window.activeTextEditor.document.getText()) + const ast = await lw.parser.parse.bib( + vscode.window.activeTextEditor.document.uri, + vscode.window.activeTextEditor.document.getText() + ) return vscode.workspace.openTextDocument({content: JSON.stringify(ast, null, 2), language: 'json'}).then(doc => vscode.window.showTextDocument(doc)) } diff --git a/src/lint/bibtex-formatter.ts b/src/lint/bibtex-formatter.ts index 39d55d7b0..6f141b8a1 100644 --- a/src/lint/bibtex-formatter.ts +++ b/src/lint/bibtex-formatter.ts @@ -58,7 +58,7 @@ async function formatDocument(document: vscode.TextDocument, sort: boolean, alig const columnOffset = range ? range.start.character : 0 logger.log('Parse active BibTeX document for AST.') - const ast = await lw.parser.parse.bib(document.getText(range)) + const ast = await lw.parser.parse.bib(document.uri, document.getText(range)) if (ast === undefined) { return [] } diff --git a/src/outline/structure/bibtex.ts b/src/outline/structure/bibtex.ts index 1d0e24d9a..294bf177d 100644 --- a/src/outline/structure/bibtex.ts +++ b/src/outline/structure/bibtex.ts @@ -28,7 +28,7 @@ export async function buildBibTeX(document: vscode.TextDocument): Promise { - const ast = await (await proxy).parseBibTeX(s, options) - if (ast instanceof Error) { - logger.logError('Error when parsing bib file.', ast) +async function bib(uri: vscode.Uri, s: string): Promise { + const ast = await (await proxy).parseBibTeX(s) + if (typeof ast === 'string') { + const err = JSON.parse(ast) as bibtexParser.SyntaxError + logger.log(`Error when parsing bib file: found ${err.found} from ${err.location.start.line}:${err.location.start.column} to ${err.location.end.line}:${err.location.end.column}.`) + bibDiagnostics.set(uri, [new vscode.Diagnostic( + new vscode.Range( + new vscode.Position(err.location.start.line - 1, err.location.start.column - 1), + new vscode.Position(err.location.end.line - 1, err.location.end.column - 1) + ), + `A BibTeX parsing error occurred. "${err.found}" is unexpected here. No BibTeX entries will be available.`, + vscode.DiagnosticSeverity.Warning + )]) return undefined } else { + bibDiagnostics.set(uri, []) return ast } } diff --git a/src/parse/parser/unified.ts b/src/parse/parser/unified.ts index 01b449351..1c6bc6fe9 100644 --- a/src/parse/parser/unified.ts +++ b/src/parse/parser/unified.ts @@ -3,6 +3,7 @@ import type * as Ast from '@unified-latex/unified-latex-types' // import { getParser } from '@unified-latex/unified-latex-util-parse' // import { attachMacroArgs } from '@unified-latex/unified-latex-util-arguments' import { bibtexParser } from 'latex-utensils' +import type { SyntaxError } from 'latex-utensils/out/types/src/pegjs/pegjs_types.js' // @ts-expect-error Load unified.js from /out/src/... import { getParser, attachMacroArgs } from '../../../../resources/unified.js' @@ -26,12 +27,12 @@ function reset(macros: Ast.MacroInfoRecord, environments: Ast.EnvInfoRecord) { unifiedParser = getParser({ macros, environments, flags: { autodetectExpl3AndAtLetter: true } }) } -function parseBibTeX(s: string, options?: bibtexParser.ParserOptions): bibtexParser.BibtexAst | Error | undefined { +function parseBibTeX(s: string): bibtexParser.BibtexAst | string | undefined { try { - return bibtexParser.parse(s, options) + return bibtexParser.parse(s) } catch (err) { - if (err instanceof Error) { - return err + if (bibtexParser.isSyntaxError(err)) { + return JSON.stringify(err) } return undefined } diff --git a/test/units/11_parser_tex.test.ts b/test/units/11_parser_tex.test.ts index 7f5298dbf..6ef082724 100644 --- a/test/units/11_parser_tex.test.ts +++ b/test/units/11_parser_tex.test.ts @@ -1,3 +1,4 @@ +import * as vscode from 'vscode' import * as path from 'path' import * as sinon from 'sinon' import { lw } from '../../src/lw' @@ -26,7 +27,7 @@ describe(path.basename(__filename).split('.')[0] + ':', () => { describe('lw.parser->bib', () => { it('should parse BibTeX content', async () => { - const ast = await parser.bib('@article{key, author = "author"}') + const ast = await parser.bib(vscode.Uri.file('/main.bib'), '@article{key, author = "author"}') assert.ok(ast) assert.strictEqual(ast.content[0].entryType, 'article') @@ -37,7 +38,7 @@ describe(path.basename(__filename).split('.')[0] + ':', () => { }) it('should log error when parsing BibTeX content fails', async () => { - const ast = await parser.bib('@article{key, author = "author",') + const ast = await parser.bib(vscode.Uri.file('/main.bib'), '@article{key, author = "author",') assert.strictEqual(ast, undefined) assert.hasLog('Error when parsing bib file.')