From 1b2e886781d1d7d1874d7801ba160d00b32cc242 Mon Sep 17 00:00:00 2001 From: James Yu Date: Wed, 4 Oct 2023 13:48:41 +0100 Subject: [PATCH] Duplabel check run only once, wording change --- src/components/cacher.ts | 4 +- src/components/duplabeldetector.ts | 89 +++++++++++++++++++++++++++ src/components/duplicatelabels.ts | 94 ----------------------------- src/components/manager.ts | 2 +- src/lw.ts | 3 +- src/providers/completer/citation.ts | 17 ++---- test/suites/utils.ts | 2 +- 7 files changed, 100 insertions(+), 111 deletions(-) create mode 100644 src/components/duplabeldetector.ts delete mode 100644 src/components/duplicatelabels.ts diff --git a/src/components/cacher.ts b/src/components/cacher.ts index be07dd769..03f57fa0e 100644 --- a/src/components/cacher.ts +++ b/src/components/cacher.ts @@ -160,6 +160,7 @@ export class Cacher { this.promises[filePath] = this.updateAST(cache).then(() => { this.updateElements(cache) }).finally(() => { + lw.dupLabelDetector.run() this.caching-- delete this.promises[filePath] lw.eventBus.fire(eventbus.FileParsed, filePath) @@ -241,14 +242,13 @@ export class Cacher { private updateElements(cache: Cache) { const start = performance.now() - lw.completer.citation.update(cache.filePath, cache.content) + lw.completer.citation.parse(cache) // Package parsing must be before command and environment. lw.completer.package.parse(cache) lw.completer.reference.parse(cache) lw.completer.glossary.parse(cache) lw.completer.environment.parse(cache) lw.completer.command.parse(cache) - lw.duplicateLabels.run(cache.filePath) this.updateBibfiles(cache) const elapsed = performance.now() - start logger.log(`Updated elements in ${elapsed.toFixed(2)} ms: ${cache.filePath} .`) diff --git a/src/components/duplabeldetector.ts b/src/components/duplabeldetector.ts new file mode 100644 index 000000000..f90683122 --- /dev/null +++ b/src/components/duplabeldetector.ts @@ -0,0 +1,89 @@ +import * as vscode from 'vscode' +import * as path from 'path' +import * as lw from '../lw' + +const duplicatedLabelsDiagnostics = vscode.languages.createDiagnosticCollection('Duplicate Labels') + +export const dupLabelDetector = { + run, + reset +} + +/** + * Compute the dictionary of labels + */ +function computeDuplicates(): string[] { + const labelsCount = new Map() + lw.cacher.getIncludedTeX().forEach(cachedFile => { + const cachedRefs = lw.cacher.get(cachedFile)?.elements.reference + if (cachedRefs === undefined) { + return + } + cachedRefs.forEach(ref => { + if (ref.range === undefined) { + return + } + let count = labelsCount.get(ref.label) + if (count === undefined) { + count = 0 + } + count += 1 + labelsCount.set(ref.label, count) + }) + }) + const duplicates = [] + for (const [label, count] of labelsCount) { + if (count > 1) { + duplicates.push(label) + } + } + return duplicates +} + +function run() { + const configuration = vscode.workspace.getConfiguration('latex-workshop') + if (!configuration.get('check.duplicatedLabels.enabled')) { + return + } + const duplicates = computeDuplicates() + showDiagnostics(duplicates) +} + +function showDiagnostics(duplicates: string[]) { + duplicatedLabelsDiagnostics.clear() + if (duplicates.length === 0) { + return + } + const diagsCollection = Object.create(null) as { [key: string]: vscode.Diagnostic[] } + + lw.cacher.getIncludedTeX().forEach(cachedFile => { + const cachedRefs = lw.cacher.get(cachedFile)?.elements.reference + if (cachedRefs === undefined) { + return + } + cachedRefs.forEach(ref => { + if (ref.range === undefined) { + return + } + if (duplicates.includes(ref.label)) { + if (! (cachedFile in diagsCollection)) { + diagsCollection[cachedFile] = [] + } + const range = ref.range instanceof vscode.Range ? ref.range : ref.range.inserting + const diag = new vscode.Diagnostic(range, `Duplicate label ${ref.label}`, vscode.DiagnosticSeverity.Warning) + diag.source = 'DuplicateLabels' + diagsCollection[cachedFile].push(diag) + } + }) + }) + + for (const file in diagsCollection) { + if (path.extname(file) === '.tex') { + duplicatedLabelsDiagnostics.set(vscode.Uri.file(file), diagsCollection[file]) + } + } +} + +function reset() { + duplicatedLabelsDiagnostics.clear() +} diff --git a/src/components/duplicatelabels.ts b/src/components/duplicatelabels.ts deleted file mode 100644 index 7f2b196eb..000000000 --- a/src/components/duplicatelabels.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as vscode from 'vscode' -import * as path from 'path' -import * as lw from '../lw' -import { getLogger } from './logger' - -const logger = getLogger('DupLabel') - - -export class DuplicateLabels { - private readonly duplicatedLabelsDiagnostics = vscode.languages.createDiagnosticCollection('Duplicate Labels') - - /** - * Compute the dictionary of labels holding their file and position - */ - private computeDuplicates(file: string): string[] { - if (!lw.cacher.get(file)) { - logger.log(`Cannot check for duplicate labels in a file not in manager: ${file} .`) - return [] - } - const labelsCount = new Map() - lw.cacher.getIncludedTeX().forEach(cachedFile => { - const cachedRefs = lw.cacher.get(cachedFile)?.elements.reference - if (cachedRefs === undefined) { - return - } - cachedRefs.forEach(ref => { - if (ref.range === undefined) { - return - } - let count = labelsCount.get(ref.label) - if (count === undefined) { - count = 0 - } - count += 1 - labelsCount.set(ref.label, count) - }) - }) - const duplicates = [] - for (const [label, count] of labelsCount) { - if (count > 1) { - duplicates.push(label) - } - } - return duplicates - } - - run(file: string) { - const configuration = vscode.workspace.getConfiguration('latex-workshop') - if (!configuration.get('check.duplicatedLabels.enabled')) { - return - } - const duplicates = this.computeDuplicates(file) - this.showDiagnostics(duplicates) - } - - private showDiagnostics(duplicates: string[]) { - this.duplicatedLabelsDiagnostics.clear() - if (duplicates.length === 0) { - return - } - const diagsCollection = Object.create(null) as { [key: string]: vscode.Diagnostic[] } - - lw.cacher.getIncludedTeX().forEach(cachedFile => { - const cachedRefs = lw.cacher.get(cachedFile)?.elements.reference - if (cachedRefs === undefined) { - return - } - cachedRefs.forEach(ref => { - if (ref.range === undefined) { - return - } - if (duplicates.includes(ref.label)) { - if (! (cachedFile in diagsCollection)) { - diagsCollection[cachedFile] = [] - } - const range = ref.range instanceof vscode.Range ? ref.range : ref.range.inserting - const diag = new vscode.Diagnostic(range, `Duplicate label ${ref.label}`, vscode.DiagnosticSeverity.Warning) - diag.source = 'DuplicateLabels' - diagsCollection[cachedFile].push(diag) - } - }) - }) - - for (const file in diagsCollection) { - if (path.extname(file) === '.tex') { - this.duplicatedLabelsDiagnostics.set(vscode.Uri.file(file), diagsCollection[file]) - } - } - } - - reset() { - this.duplicatedLabelsDiagnostics.clear() - } -} diff --git a/src/components/manager.ts b/src/components/manager.ts index bc5b9a06f..3594c787b 100644 --- a/src/components/manager.ts +++ b/src/components/manager.ts @@ -303,7 +303,7 @@ export class Manager { // We also clean the completions from the old project lw.completer.input.reset() - lw.duplicateLabels.reset() + lw.dupLabelDetector.reset() lw.cacher.src.reset() lw.cacher.add(rootFile) void lw.cacher.refreshCache(rootFile).then(async () => { diff --git a/src/lw.ts b/src/lw.ts index aa1401e64..c5f1a2f45 100644 --- a/src/lw.ts +++ b/src/lw.ts @@ -6,7 +6,7 @@ import { Cleaner } from './components/cleaner' import { LaTeXCommanderTreeView } from './components/commander' import { Configuration } from './components/configuration' import { Counter } from './components/counter' -import { DuplicateLabels } from './components/duplicatelabels' +export { dupLabelDetector } from './components/duplabeldetector' import { EnvPair } from './components/envpair' import { EventBus } from './components/eventbus' import { Linter } from './components/linter' @@ -55,7 +55,6 @@ export const server = new Server() export const locator = new Locator() export const completer = new Completer() export const atSuggestionCompleter = new AtSuggestionCompleter() -export const duplicateLabels = new DuplicateLabels() export const linter = new Linter() export const cleaner = new Cleaner() export const counter = new Counter() diff --git a/src/providers/completer/citation.ts b/src/providers/completer/citation.ts index aa8b31999..663e79eaf 100644 --- a/src/providers/completer/citation.ts +++ b/src/providers/completer/citation.ts @@ -8,6 +8,7 @@ import {computeFilteringRange} from './completerutils' import type { IProvider, ICompletionItem, IProviderArgs } from '../completion' import { getLogger } from '../../components/logger' import { parser } from '../../components/parser' +import { Cache } from '../../components/cacher' const logger = getLogger('Intelli', 'Citation') @@ -342,18 +343,12 @@ export class Citation implements IProvider { } /** - * Updates the Manager cache for bibitems defined in `file`. - * `content` is parsed with regular expressions, - * and the result is used to update the cache. - * - * @param file The path of a LaTeX file. - * @param content The content of a LaTeX file. + * Updates the Manager cache for bibitems with Cache. + * Cache `content` is parsed with regular expressions, + * and the result is used to update the cache bibitem element. */ - update(file: string, content: string) { - const cache = lw.cacher.get(file) - if (cache !== undefined) { - cache.elements.bibitem = this.parseContent(file, content) - } + parse(cache: Cache) { + cache.elements.bibitem = this.parseContent(cache.filePath, cache.content) } private parseContent(file: string, content: string): CiteSuggestion[] { diff --git a/test/suites/utils.ts b/test/suites/utils.ts index ae86de02e..93357dc73 100644 --- a/test/suites/utils.ts +++ b/test/suites/utils.ts @@ -79,7 +79,7 @@ export async function reset() { lw.manager.rootFile = undefined lw.manager.localRootFile = undefined lw.completer.input.reset() - lw.duplicateLabels.reset() + lw.dupLabelDetector.reset() lw.cacher.reset() glob.sync('**/{**.tex,**.pdf,**.bib}', { cwd: getFixture() }).forEach(file => { try {fs.unlinkSync(path.resolve(getFixture(), file))} catch {} }) }