From 0d5e3817f0a661b65a16c3ada5ac742a90f21cf9 Mon Sep 17 00:00:00 2001 From: Agustin Groh Date: Tue, 9 Jun 2026 09:44:18 -0300 Subject: [PATCH] fix(dependency):SP-4443 scan dependencies with include all files types option enabled --- CHANGELOG.md | 1 + .../task/scanner/dependency/DependencyTask.ts | 22 ++++++++++- .../tree/blackList/BlackListDependencies.ts | 38 +++++++++++-------- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad354e5d4..c3380e1a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Importing a `result.json` no longer fails when a result has an empty `version` or `latest` value. - Snippet match highlight in the compare view no longer disappears after scrolling: the match is now marked on the scrollbar, and scrolling one editor keeps the other aligned on its corresponding match. +- Dependency scanning no longer crashes when a project is scanned with **Include all file types** enabled. ## [1.39.2] - 2026-05-13 ### Fixed diff --git a/src/main/task/scanner/dependency/DependencyTask.ts b/src/main/task/scanner/dependency/DependencyTask.ts index d4a5d36e4..5851a548b 100644 --- a/src/main/task/scanner/dependency/DependencyTask.ts +++ b/src/main/task/scanner/dependency/DependencyTask.ts @@ -3,7 +3,7 @@ import { ScannerFactory } from '../ScannerFactory'; import fs from 'fs'; import log from 'electron-log'; import i18next from 'i18next'; -import { BlackListDependencies } from '../../../workspace/tree/blackList/BlackListDependencies'; +import { BlackListDependencies, DependencyFilterRule } from '../../../workspace/tree/blackList/BlackListDependencies'; import { Project } from '../../../workspace/Project'; import { dependencyService } from '../../../services/DependencyService'; import { Scanner } from '../types'; @@ -34,12 +34,30 @@ export class DependencyTask implements Scanner.IPipelineTask { return true; } + /** + * Reads the folder-filter rules used to exclude paths from dependency scanning. + * + * `filter.json` is written during indexing only when project-level file filtering + * is active. When a project is scanned with "Include all file types" enabled the + * file is never created, so there are no rules to apply: an empty list is returned + * (nothing excluded) instead of letting a missing file crash the dependency stage. + */ + private async loadDependencyFilterRules(): Promise { + const filterPath = `${this.project.metadata.getMyPath()}/filter.json`; + if (!fs.existsSync(filterPath)) { + log.info('[ DependencyTask ]: filter.json not found, skipping dependency filters (all extensions enabled)'); + return []; + } + const raw = await fs.promises.readFile(filterPath, 'utf8'); + return JSON.parse(raw).filters ?? []; + } + private async scanDependencies() { try { const allFiles = []; const rootPath = this.project.metadata.getScanRoot(); const collector = new CollectFilesVisitor( - new BlackListDependencies(`${this.project.metadata.getMyPath()}/filter.json`), + new BlackListDependencies(await this.loadDependencyFilterRules()), ); this.project.tree.getRootFolder().accept(collector); collector.files.forEach((f) => { diff --git a/src/main/workspace/tree/blackList/BlackListDependencies.ts b/src/main/workspace/tree/blackList/BlackListDependencies.ts index f06a1378a..48de12446 100644 --- a/src/main/workspace/tree/blackList/BlackListDependencies.ts +++ b/src/main/workspace/tree/blackList/BlackListDependencies.ts @@ -1,25 +1,33 @@ -import * as fs from 'fs'; import { NameFilter, AbstractFilter } from '../../filtering'; import { BlackListAbstract } from './BlackListAbstract'; -import Node, { NodeStatus } from '../Node'; +import Node from '../Node'; + +/** Shape of a single filter rule as persisted in the project's `filter.json`. */ +export interface DependencyFilterRule { + ftype: string; + scope: string; + condition: string; + value: string; +} export class BlackListDependencies extends BlackListAbstract { private filters: Array = []; - public constructor(path: string) { + /** + * Builds the dependency blacklist from filter rules (as persisted in the + * project's `filter.json`). Only NAME/FOLDER rules are applied. + * + * Reading the rules from disk is intentionally left to the caller: this class + * only owns the filtering logic, mirroring the other BlackList* filters which + * keep their rules in memory. An empty list means nothing is excluded — e.g. + * when a project is scanned with "Include all file types" enabled, no + * `filter.json` is generated and the caller passes no rules. + */ + public constructor(rules: Array = []) { super(); - this.load(path); - } - - private load(path: string) { - const file = fs.readFileSync(path, 'utf8'); - const f = JSON.parse(file); - const { filters } = f; - - let i: number; - for (i = 0; i < filters.length; i += 1) { - if (filters[i].ftype === 'NAME' && filters[i].scope === 'FOLDER') this.filters.push(new NameFilter(filters[i].condition, filters[i].value, filters[i].scope)); - } + rules + .filter((rule) => rule.ftype === 'NAME' && rule.scope === 'FOLDER') + .forEach((rule) => this.filters.push(new NameFilter(rule.condition, rule.value, rule.scope))); } public evaluate(node: Node): boolean {