From 574f67d933ec859d9c26ab7099ffc085ddb4e76d Mon Sep 17 00:00:00 2001 From: BoxBoxJason Date: Sun, 22 Mar 2026 02:58:45 +0100 Subject: [PATCH 1/4] fix: ignore some directories & files in files achievements Signed-off-by: BoxBoxJason --- src/listeners/files.ts | 104 ++++++++++++++++++++++----- src/test/listeners/files.test.ts | 118 +++++++++++++++++++++++++++++-- 2 files changed, 199 insertions(+), 23 deletions(-) diff --git a/src/listeners/files.ts b/src/listeners/files.ts index a7c255d..8c743b6 100644 --- a/src/listeners/files.ts +++ b/src/listeners/files.ts @@ -12,6 +12,49 @@ import path from "node:path"; import logger from "../utils/logger"; import { config } from "../config/config"; +// Define ignored paths and files for progression counting (directory names, case sensitive) +const IGNORED_PATH_SEGMENTS = new Set([ + ".git", + ".svn", + ".hg", + ".jj", + "node_modules", +]); + +// Define ignored file names for progression counting (case-insensitive) +const IGNORED_FILE_NAMES = new Set([ + "package-lock.json", + "yarn.lock", + "pnpm-lock.yaml", + "bun.lockb", + ".ds_store", + "thumbs.db", +]); + +/** + * Check if a given URI should be ignored for progression counting based on its path and file name. + * + * @param {vscode.Uri} uri - The URI to check + * @returns {boolean} True if the URI should be ignored, false otherwise + */ +function shouldIgnoreUri(uri: vscode.Uri): boolean { + if (uri.scheme !== "file") { + return true; + } + + const normalizedPath = path.normalize(uri.fsPath); + const segments = normalizedPath + .split(path.sep) + .map((segment) => segment.toLowerCase()); + + if (segments.some((segment) => IGNORED_PATH_SEGMENTS.has(segment))) { + return true; + } + + const fileName = path.basename(normalizedPath).toLowerCase(); + return IGNORED_FILE_NAMES.has(fileName); +} + /** * File related events listeners functions and handlers * @@ -36,36 +79,36 @@ export namespace fileListeners { "**/*", false, false, - false + false, ); resourcesWatcher.onDidCreate( handleCreateEvent, null, - context.subscriptions + context.subscriptions, ); resourcesWatcher.onDidDelete( handleDeleteEvent, null, - context.subscriptions + context.subscriptions, ); vscode.workspace.onDidRenameFiles( handleRenameEvent, null, - context.subscriptions + context.subscriptions, ); // Text document changes vscode.workspace.onDidChangeTextDocument( handleTextChangedEvent, null, - context.subscriptions + context.subscriptions, ); // Diagnostics changes vscode.languages.onDidChangeDiagnostics( handleDiagnosticChangedEvent, null, - context.subscriptions + context.subscriptions, ); logger.debug("File listeners activated"); @@ -83,11 +126,15 @@ export namespace fileListeners { * @returns {Promise} */ export async function handleCreateEvent(uri: vscode.Uri): Promise { + if (shouldIgnoreUri(uri)) { + return; + } + const stats = await vscode.workspace.fs.stat(uri); if (stats.type === vscode.FileType.File) { // Increase file created count await ProgressionController.increaseProgression( - constants.criteria.FILES_CREATED + constants.criteria.FILES_CREATED, ); // Retrieve file extension @@ -102,7 +149,7 @@ export namespace fileListeners { } else if (stats.type === vscode.FileType.Directory) { // Increase directory created count await ProgressionController.increaseProgression( - constants.criteria.DIRECTORY_CREATED + constants.criteria.DIRECTORY_CREATED, ); } } @@ -116,8 +163,12 @@ export namespace fileListeners { * @returns {Promise} */ export async function handleDeleteEvent(uri: vscode.Uri): Promise { + if (shouldIgnoreUri(uri)) { + return; + } + await ProgressionController.increaseProgression( - constants.criteria.RESOURCE_DELETED + constants.criteria.RESOURCE_DELETED, ); } @@ -130,11 +181,20 @@ export namespace fileListeners { * @returns {Promise} */ export async function handleRenameEvent( - event: vscode.FileRenameEvent + event: vscode.FileRenameEvent, ): Promise { + const relevantFileCount = event.files.filter( + ({ oldUri, newUri }) => + !shouldIgnoreUri(oldUri) && !shouldIgnoreUri(newUri), + ).length; + + if (relevantFileCount === 0) { + return; + } + await ProgressionController.increaseProgression( constants.criteria.FILES_RENAMED, - event.files.length + relevantFileCount, ); } @@ -147,8 +207,12 @@ export namespace fileListeners { * @returns {Promise} */ export async function handleTextChangedEvent( - event: vscode.TextDocumentChangeEvent + event: vscode.TextDocumentChangeEvent, ): Promise { + if (shouldIgnoreUri(event.document.uri)) { + return; + } + const language = constants.labels.LANGUAGES_EXTENSIONS[ path.extname(event.document.fileName) @@ -163,19 +227,19 @@ export namespace fileListeners { // Increment progression for the added lines await ProgressionController.increaseProgression( constants.criteria.LINES_OF_CODE_LANGUAGE.replace("%s", language), - totalLinesAdded + totalLinesAdded, ); // Increment generic lines of code progression await ProgressionController.increaseProgression( constants.criteria.LINES_OF_CODE, - totalLinesAdded + totalLinesAdded, ); } } } function countLinesAdded( - change: vscode.TextDocumentContentChangeEvent + change: vscode.TextDocumentContentChangeEvent, ): number { // Check if the change involves adding new lines if (change.text.includes("\n")) { @@ -195,16 +259,20 @@ export namespace fileListeners { let errorCounterFree = true; export async function handleDiagnosticChangedEvent( - event: vscode.DiagnosticChangeEvent + event: vscode.DiagnosticChangeEvent, ): Promise { if (errorCounterFree) { errorCounterFree = false; for (const uri of event.uris) { + if (shouldIgnoreUri(uri)) { + continue; + } + const errorCount = vscode.languages .getDiagnostics(uri) .filter( (diagnostic) => - diagnostic.severity === vscode.DiagnosticSeverity.Error + diagnostic.severity === vscode.DiagnosticSeverity.Error, ).length; const filePath = uri.fsPath; const previousErrorCount = fileErrorCounts.get(filePath); @@ -212,7 +280,7 @@ export namespace fileListeners { if (errorCount < previousErrorCount) { await ProgressionController.increaseProgression( constants.criteria.ERRORS_FIXED, - previousErrorCount - errorCount + previousErrorCount - errorCount, ); } } diff --git a/src/test/listeners/files.test.ts b/src/test/listeners/files.test.ts index d151e07..ee34f1e 100644 --- a/src/test/listeners/files.test.ts +++ b/src/test/listeners/files.test.ts @@ -40,7 +40,7 @@ suite("File Listeners Test Suite", () => { // So criteria: FILES_CREATED_TypeScript const langCriteria = constants.criteria.FILES_CREATED_LANGUAGE.replace( "%s", - "TypeScript" + "TypeScript", ); if (constants.labels.LANGUAGES_EXTENSIONS[".ts"] === "TypeScript") { assert.ok(increasedCriteria.includes(langCriteria)); @@ -69,7 +69,7 @@ suite("File Listeners Test Suite", () => { await fileListeners.handleCreateEvent(uri); assert.strictEqual( increasedCriteria, - constants.criteria.DIRECTORY_CREATED + constants.criteria.DIRECTORY_CREATED, ); } finally { ProgressionController.increaseProgression = originalIncrease; @@ -93,13 +93,121 @@ suite("File Listeners Test Suite", () => { await fileListeners.handleDeleteEvent(uri); assert.strictEqual( increasedCriteria, - constants.criteria.RESOURCE_DELETED + constants.criteria.RESOURCE_DELETED, ); } finally { ProgressionController.increaseProgression = originalIncrease; } }); + test("handleCreateEvent should ignore files under .git and node_modules", async () => { + const ignoredGitUri = vscode.Uri.file( + path.join(tempDir, ".git", "objects", "tmp"), + ); + const ignoredNodeModulesUri = vscode.Uri.file( + path.join(tempDir, "node_modules", "pkg", "index.js"), + ); + + let callCount = 0; + const originalIncrease = ProgressionController.increaseProgression; + ProgressionController.increaseProgression = async () => { + callCount++; + }; + + try { + await fileListeners.handleCreateEvent(ignoredGitUri); + await fileListeners.handleCreateEvent(ignoredNodeModulesUri); + assert.strictEqual(callCount, 0); + } finally { + ProgressionController.increaseProgression = originalIncrease; + } + }); + + test("handleDeleteEvent should ignore lock files", async () => { + const ignoredUri = vscode.Uri.file(path.join(tempDir, "package-lock.json")); + + let callCount = 0; + const originalIncrease = ProgressionController.increaseProgression; + ProgressionController.increaseProgression = async () => { + callCount++; + }; + + try { + await fileListeners.handleDeleteEvent(ignoredUri); + assert.strictEqual(callCount, 0); + } finally { + ProgressionController.increaseProgression = originalIncrease; + } + }); + + test("handleRenameEvent should only count non-ignored paths", async () => { + const event: vscode.FileRenameEvent = { + files: [ + { + oldUri: vscode.Uri.file(path.join(tempDir, "src", "a.ts")), + newUri: vscode.Uri.file(path.join(tempDir, "src", "b.ts")), + }, + { + oldUri: vscode.Uri.file(path.join(tempDir, ".git", "tmpA")), + newUri: vscode.Uri.file(path.join(tempDir, ".git", "tmpB")), + }, + ], + }; + + let calls: Array<{ criteria: string; amount: number | string }> = []; + const originalIncrease = ProgressionController.increaseProgression; + ProgressionController.increaseProgression = async ( + criteria: string, + amount: number | string = 1, + ) => { + calls.push({ criteria, amount }); + }; + + try { + await fileListeners.handleRenameEvent(event); + assert.strictEqual(calls.length, 1); + assert.strictEqual(calls[0]?.criteria, constants.criteria.FILES_RENAMED); + assert.strictEqual(Number(calls[0]?.amount), 1); + } finally { + ProgressionController.increaseProgression = originalIncrease; + } + }); + + test("handleTextChangedEvent should ignore files in generated folders", async () => { + const testFile = path.join(tempDir, "node_modules", "bundle.ts"); + const uri = vscode.Uri.file(testFile); + const document = { + fileName: testFile, + uri: uri, + } as vscode.TextDocument; + + const event = { + document: document, + reason: undefined, + contentChanges: [ + { + range: new vscode.Range(0, 0, 0, 0), + rangeOffset: 0, + rangeLength: 0, + text: "new line\n", + }, + ], + } as vscode.TextDocumentChangeEvent; + + let callCount = 0; + const originalIncrease = ProgressionController.increaseProgression; + ProgressionController.increaseProgression = async () => { + callCount++; + }; + + try { + await fileListeners.handleTextChangedEvent(event); + assert.strictEqual(callCount, 0); + } finally { + ProgressionController.increaseProgression = originalIncrease; + } + }); + test("handleTextChangedEvent should batch line updates", async () => { const testFile = path.join(tempDir, "test.ts"); const uri = vscode.Uri.file(testFile); @@ -132,7 +240,7 @@ suite("File Listeners Test Suite", () => { const originalIncrease = ProgressionController.increaseProgression; ProgressionController.increaseProgression = async ( criteria: string, - amount: number | string = 1 + amount: number | string = 1, ) => { if (criteria === constants.criteria.LINES_OF_CODE) { callCount++; @@ -145,7 +253,7 @@ suite("File Listeners Test Suite", () => { assert.strictEqual( callCount, 1, - "Should call increaseProgression once for generic lines" + "Should call increaseProgression once for generic lines", ); assert.strictEqual(totalLines, 3, "Should sum up all lines (1 + 2)"); } finally { From 906f78eff69b2d74bb0249bc963f8548651b9bfc Mon Sep 17 00:00:00 2001 From: BoxBoxJason Date: Sun, 22 Mar 2026 03:12:56 +0100 Subject: [PATCH 2/4] feat: make ignore directories & files configurable Signed-off-by: BoxBoxJason --- package.json | 29 ++++++++++++++++++++++++++ src/config/config.ts | 29 ++++++++++++++++++++++++++ src/listeners/files.ts | 46 ++++++++++++++++++++++++++---------------- 3 files changed, 87 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index a86852c..13dd2c1 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,35 @@ "type": "boolean", "default": true, "description": "Enable or disable time events listeners for the Achievements extension." + }, + "achievements.ignore.files": { + "type": "array", + "default": [ + "package-lock.json", + "yarn.lock", + "pnpm-lock.yaml", + "bun.lockb", + ".ds_store", + "thumbs.db" + ], + "items": { + "type": "string" + }, + "description": "File names ignored by file-related achievements (case-insensitive)." + }, + "achievements.ignore.directories": { + "type": "array", + "default": [ + ".git", + ".svn", + ".hg", + ".jj", + "node_modules" + ], + "items": { + "type": "string" + }, + "description": "Directory names ignored by file-related achievements (case-sensitive)." } } } diff --git a/src/config/config.ts b/src/config/config.ts index b546f7d..da044d1 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -19,6 +19,10 @@ export interface Config { notifications: boolean; logDirectory: string; username: string; + ignore: { + files: string[]; + directories: string[]; + }; listeners: { debug: boolean; extensions: boolean; @@ -125,6 +129,31 @@ export namespace config { username: extensionRawConfig .get("username", webview.DEFAULT_USER) .trim(), + ignore: { + files: extensionRawConfig + .get("ignore.files", [ + "package-lock.json", + "yarn.lock", + "pnpm-lock.yaml", + "bun.lockb", + ".ds_store", + "thumbs.db", + ]) + .filter((name) => typeof name === "string") + .map((name) => name.trim()) + .filter((name) => name.length > 0), + directories: extensionRawConfig + .get("ignore.directories", [ + ".git", + ".svn", + ".hg", + ".jj", + "node_modules", + ]) + .filter((name) => typeof name === "string") + .map((name) => name.trim()) + .filter((name) => name.length > 0), + }, listeners: { debug: extensionRawConfig.get("listeners.debug", true), extensions: extensionRawConfig.get( diff --git a/src/listeners/files.ts b/src/listeners/files.ts index 8c743b6..afa0b12 100644 --- a/src/listeners/files.ts +++ b/src/listeners/files.ts @@ -12,24 +12,22 @@ import path from "node:path"; import logger from "../utils/logger"; import { config } from "../config/config"; -// Define ignored paths and files for progression counting (directory names, case sensitive) -const IGNORED_PATH_SEGMENTS = new Set([ - ".git", - ".svn", - ".hg", - ".jj", - "node_modules", -]); - -// Define ignored file names for progression counting (case-insensitive) -const IGNORED_FILE_NAMES = new Set([ +const DEFAULT_IGNORED_FILES = [ "package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lockb", ".ds_store", "thumbs.db", -]); +]; + +const DEFAULT_IGNORED_DIRECTORIES = [ + ".git", + ".svn", + ".hg", + ".jj", + "node_modules", +]; /** * Check if a given URI should be ignored for progression counting based on its path and file name. @@ -42,17 +40,31 @@ function shouldIgnoreUri(uri: vscode.Uri): boolean { return true; } + const extensionRawConfig = vscode.workspace.getConfiguration("achievements"); + const ignoredDirectoryNames = new Set( + extensionRawConfig + .get("ignore.directories", DEFAULT_IGNORED_DIRECTORIES) + .filter((name) => typeof name === "string") + .map((name) => name.trim()) + .filter((name) => name.length > 0), + ); + const ignoredFileNames = new Set( + extensionRawConfig + .get("ignore.files", DEFAULT_IGNORED_FILES) + .filter((name) => typeof name === "string") + .map((name) => name.trim().toLowerCase()) + .filter((name) => name.length > 0), + ); + const normalizedPath = path.normalize(uri.fsPath); - const segments = normalizedPath - .split(path.sep) - .map((segment) => segment.toLowerCase()); + const segments = normalizedPath.split(path.sep); - if (segments.some((segment) => IGNORED_PATH_SEGMENTS.has(segment))) { + if (segments.some((segment) => ignoredDirectoryNames.has(segment))) { return true; } const fileName = path.basename(normalizedPath).toLowerCase(); - return IGNORED_FILE_NAMES.has(fileName); + return ignoredFileNames.has(fileName); } /** From c70fca580f92d72113417caf53aec296a97385a2 Mon Sep 17 00:00:00 2001 From: BoxBoxJason Date: Sun, 22 Mar 2026 03:14:55 +0100 Subject: [PATCH 3/4] docs: explain parameter in README Signed-off-by: BoxBoxJason --- README.md | 2 ++ src/config/config.ts | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9535445..2517997 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,8 @@ You can also access the settings by using the command `achievements.settings`. |`achievements.listeners.tabs`|Enable or disable tab listeners| |`achievements.listeners.tasks`|Enable or disable task listeners| |`achievements.listeners.time`|Enable or disable time tracking listeners| +|`achievements.ignore.files`|List of file names ignored by file-based achievements (case-insensitive, for example `package-lock.json` matches `PACKAGE-LOCK.JSON`)| +|`achievements.ignore.directories`|List of directory names ignored by file-based achievements (case-sensitive, for example `.git` matches only `.git`)| ## Installation diff --git a/src/config/config.ts b/src/config/config.ts index da044d1..af1ee5a 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -86,7 +86,7 @@ export namespace config { vscode.window .showInformationMessage( "For a better experience, please set your username", - "Set Username" + "Set Username", ) .then((selection) => { if (selection === "Set Username") { @@ -158,7 +158,7 @@ export namespace config { debug: extensionRawConfig.get("listeners.debug", true), extensions: extensionRawConfig.get( "listeners.extensions", - true + true, ), files: extensionRawConfig.get("listeners.files", true), git: extensionRawConfig.get("listeners.git", true), @@ -171,7 +171,7 @@ export namespace config { // Check if the log directory is a valid path, if not, set it to the default if (!path.isAbsolute(extensionConfig.logDirectory)) { logger.warn( - `Invalid log directory path: ${extensionConfig.logDirectory}, setting to default` + `Invalid log directory path: ${extensionConfig.logDirectory}, setting to default`, ); updateConfig("logDirectory", defaultLogDir); extensionConfig.logDirectory = defaultLogDir; @@ -180,7 +180,7 @@ export namespace config { fs.mkdirSync(extensionConfig.logDirectory, { recursive: true }); } catch (error) { logger.error( - `Error creating log directory: ${error}, setting to default` + `Error creating log directory: ${error}, setting to default`, ); updateConfig("logDirectory", defaultLogDir); extensionConfig.logDirectory = defaultLogDir; @@ -261,7 +261,7 @@ export namespace config { } export function isListenerEnabled( - listener: keyof Config["listeners"] + listener: keyof Config["listeners"], ): boolean { const listeners = getConfig().listeners; From 0defdec2d7df98bdd254b03e84208ab2160aafa5 Mon Sep 17 00:00:00 2001 From: BoxBoxJason Date: Sun, 22 Mar 2026 03:41:21 +0100 Subject: [PATCH 4/4] fix: cache, duplication, missing tests Signed-off-by: BoxBoxJason --- src/config/config.ts | 16 ++----- src/constants.ts | 12 ++++++ src/listeners/files.ts | 73 ++++++++++++++++++-------------- src/test/listeners/files.test.ts | 33 +++++++++++++++ 4 files changed, 90 insertions(+), 44 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index af1ee5a..2b6299a 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -10,6 +10,7 @@ import fs from "fs"; import logger from "../utils/logger"; import * as vscode from "vscode"; import { webview } from "../views/viewconst"; +import { constants } from "../constants"; // ==================== TYPES ==================== // Config interface, defines the structure of the config object, always json serializable @@ -131,24 +132,13 @@ export namespace config { .trim(), ignore: { files: extensionRawConfig - .get("ignore.files", [ - "package-lock.json", - "yarn.lock", - "pnpm-lock.yaml", - "bun.lockb", - ".ds_store", - "thumbs.db", - ]) + .get("ignore.files", [...constants.ignore.DEFAULT_FILES]) .filter((name) => typeof name === "string") .map((name) => name.trim()) .filter((name) => name.length > 0), directories: extensionRawConfig .get("ignore.directories", [ - ".git", - ".svn", - ".hg", - ".jj", - "node_modules", + ...constants.ignore.DEFAULT_DIRECTORIES, ]) .filter((name) => typeof name === "string") .map((name) => name.trim()) diff --git a/src/constants.ts b/src/constants.ts index 4dfaa2e..e053fd5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -223,4 +223,16 @@ export namespace constants { TASKS: "tasks", TIME: "time", } as const; + + export const ignore = { + DEFAULT_FILES: [ + "package-lock.json", + "yarn.lock", + "pnpm-lock.yaml", + "bun.lockb", + ".ds_store", + "thumbs.db", + ], + DEFAULT_DIRECTORIES: [".git", ".svn", ".hg", ".jj", "node_modules"], + } as const; } diff --git a/src/listeners/files.ts b/src/listeners/files.ts index afa0b12..09a277a 100644 --- a/src/listeners/files.ts +++ b/src/listeners/files.ts @@ -12,49 +12,45 @@ import path from "node:path"; import logger from "../utils/logger"; import { config } from "../config/config"; -const DEFAULT_IGNORED_FILES = [ - "package-lock.json", - "yarn.lock", - "pnpm-lock.yaml", - "bun.lockb", - ".ds_store", - "thumbs.db", -]; - -const DEFAULT_IGNORED_DIRECTORIES = [ - ".git", - ".svn", - ".hg", - ".jj", - "node_modules", -]; - -/** - * Check if a given URI should be ignored for progression counting based on its path and file name. - * - * @param {vscode.Uri} uri - The URI to check - * @returns {boolean} True if the URI should be ignored, false otherwise - */ -function shouldIgnoreUri(uri: vscode.Uri): boolean { - if (uri.scheme !== "file") { - return true; - } +let ignoredDirectoryNames = new Set(); +let ignoredFileNames = new Set(); +function refreshIgnoredMatchers(): void { const extensionRawConfig = vscode.workspace.getConfiguration("achievements"); - const ignoredDirectoryNames = new Set( + + ignoredDirectoryNames = new Set( extensionRawConfig - .get("ignore.directories", DEFAULT_IGNORED_DIRECTORIES) + .get("ignore.directories", [ + ...constants.ignore.DEFAULT_DIRECTORIES, + ]) .filter((name) => typeof name === "string") .map((name) => name.trim()) .filter((name) => name.length > 0), ); - const ignoredFileNames = new Set( + + ignoredFileNames = new Set( extensionRawConfig - .get("ignore.files", DEFAULT_IGNORED_FILES) + .get("ignore.files", [...constants.ignore.DEFAULT_FILES]) .filter((name) => typeof name === "string") .map((name) => name.trim().toLowerCase()) .filter((name) => name.length > 0), ); +} + +/** + * Check if a given URI should be ignored for progression counting based on its path and file name. + * + * @param {vscode.Uri} uri - The URI to check + * @returns {boolean} True if the URI should be ignored, false otherwise + */ +function shouldIgnoreUri(uri: vscode.Uri): boolean { + if (uri.scheme !== "file") { + return true; + } + + if (ignoredDirectoryNames.size === 0 && ignoredFileNames.size === 0) { + refreshIgnoredMatchers(); + } const normalizedPath = path.normalize(uri.fsPath); const segments = normalizedPath.split(path.sep); @@ -86,6 +82,8 @@ export namespace fileListeners { if (config.isListenerEnabled(constants.listeners.FILES)) { logger.info("Starting file events listeners"); + refreshIgnoredMatchers(); + // Watcher for resources const resourcesWatcher = vscode.workspace.createFileSystemWatcher( "**/*", @@ -123,6 +121,19 @@ export namespace fileListeners { context.subscriptions, ); + vscode.workspace.onDidChangeConfiguration( + (event) => { + if ( + event.affectsConfiguration("achievements.ignore.files") || + event.affectsConfiguration("achievements.ignore.directories") + ) { + refreshIgnoredMatchers(); + } + }, + null, + context.subscriptions, + ); + logger.debug("File listeners activated"); } else { logger.info("File listeners are disabled"); diff --git a/src/test/listeners/files.test.ts b/src/test/listeners/files.test.ts index ee34f1e..95d3274 100644 --- a/src/test/listeners/files.test.ts +++ b/src/test/listeners/files.test.ts @@ -260,4 +260,37 @@ suite("File Listeners Test Suite", () => { ProgressionController.increaseProgression = originalIncrease; } }); + + test("handleDiagnosticChangedEvent should ignore configured URIs", async () => { + const ignoredUri = vscode.Uri.file( + path.join(tempDir, "node_modules", "broken.ts"), + ); + + const originalIncrease = ProgressionController.increaseProgression; + const originalGetDiagnostics = vscode.languages.getDiagnostics; + let progressionCalls = 0; + + ProgressionController.increaseProgression = async () => { + progressionCalls++; + }; + + (vscode.languages as any).getDiagnostics = () => [ + { severity: vscode.DiagnosticSeverity.Error }, + ]; + + try { + await fileListeners.handleDiagnosticChangedEvent({ + uris: [ignoredUri], + } as vscode.DiagnosticChangeEvent); + + await fileListeners.handleDiagnosticChangedEvent({ + uris: [ignoredUri], + } as vscode.DiagnosticChangeEvent); + + assert.strictEqual(progressionCalls, 0); + } finally { + ProgressionController.increaseProgression = originalIncrease; + (vscode.languages as any).getDiagnostics = originalGetDiagnostics; + } + }); });