From f2e79c3153f9a07f2aaf581ecd4d1b14ea0c0715 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 2 Aug 2024 09:58:00 -0600 Subject: [PATCH] fix: recurse through dirs then files (#1381) * fix: recurse through dirs then files * fix: working * fix: cleanup, remove unnecessary break * test: renable skipped test * test: revert ut assertions, ensure order * chore: cleanup, UT --- .../decomposedMetadataTransformer.ts | 5 +++ src/resolve/metadataResolver.ts | 16 ++++++- test/resolve/metadataResolver.test.ts | 43 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/convert/transformers/decomposedMetadataTransformer.ts b/src/convert/transformers/decomposedMetadataTransformer.ts index 430fc612bf..fced068fe4 100644 --- a/src/convert/transformers/decomposedMetadataTransformer.ts +++ b/src/convert/transformers/decomposedMetadataTransformer.ts @@ -46,6 +46,11 @@ export class DecomposedMetadataTransformer extends BaseMetadataTransformer { component, children: new ComponentSet([], this.registry), }; + if (component.xml && existing.component && !existing.component.xml) { + // we've already found and created the parent of this component on L~38 + // but now we have more information about the parent (xml) that we didn't have before, so add it + existing.component = component; + } (component.getChildren() ?? []).map((child) => { existing.children?.add(child); }); diff --git a/src/resolve/metadataResolver.ts b/src/resolve/metadataResolver.ts index 622f2c61f8..a70dabc4c3 100644 --- a/src/resolve/metadataResolver.ts +++ b/src/resolve/metadataResolver.ts @@ -76,7 +76,12 @@ export class MetadataResolver { return components; } - for (const fsPath of this.tree.readDirectory(dir).map(fnJoin(dir))) { + for (const fsPath of this.tree + .readDirectory(dir) + .map(fnJoin(dir)) + // this method isn't truly recursive, we need to sort directories before files so we look as far down as possible + // before finding the parent and returning only it - by sorting, we make it as recursive as possible + .sort(this.sortDirsFirst)) { if (ignore.has(fsPath)) { continue; } @@ -117,6 +122,15 @@ export class MetadataResolver { return components.concat(dirQueue.flatMap((d) => this.getComponentsFromPathRecursive(d, inclusiveFilter))); } + private sortDirsFirst = (a: string, b: string): number => { + if (this.tree.isDirectory(a) && this.tree.isDirectory(b)) { + return 0; + } else if (this.tree.isDirectory(a) && !this.tree.isDirectory(b)) { + return -1; + } else { + return 1; + } + }; private resolveComponent(fsPath: string, isResolvingSource: boolean): SourceComponent | undefined { if (this.forceIgnore?.denies(fsPath)) { // don't resolve the component if the path is denied diff --git a/test/resolve/metadataResolver.test.ts b/test/resolve/metadataResolver.test.ts index 1a5f88bf35..81fb752f1a 100644 --- a/test/resolve/metadataResolver.test.ts +++ b/test/resolve/metadataResolver.test.ts @@ -9,6 +9,7 @@ import { basename, dirname, join } from 'node:path'; import { assert, expect } from 'chai'; import { Messages, SfError } from '@salesforce/core'; import { ensureString } from '@salesforce/ts-types'; +import { createSandbox } from 'sinon'; import { ComponentSet, MetadataResolver, @@ -290,6 +291,48 @@ describe('MetadataResolver', () => { expect(access.getComponentsFromPath(path)).to.deep.equal(xmlInFolder.COMPONENTS); }); + it('should parse dirs before files', () => { + const path = xmlInFolder.COMPONENT_FOLDER_PATH; + const env = createSandbox(); + + const access = testUtil.createMetadataResolver([ + { + dirPath: path, + children: ['dir1', { name: 'parent.report-meta.xml', data: Buffer.from('Some Data') }], + }, + { + dirPath: join(path, 'dir1'), + children: [{ name: 'dir1.report-meta.xml', data: Buffer.from('Some Data') }], + }, + ]); + // @ts-ignore + const isDirSpy = env.spy(access.tree, 'isDirectory'); + + const componentMappings = xmlInFolder.COMPONENTS.map((c: SourceComponent) => ({ + path: ensureString(c.xml), + component: c, + })); + testUtil.stubAdapters([ + { + type: registry.types.report, + componentMappings, + allowContent: false, + }, + ]); + access.getComponentsFromPath(path); + // isDirectory is called a few times during recursive parsing, after debugging + // we only need to verify calls made in succession are called with dirs, and then files + expect([isDirSpy.args[3][0], isDirSpy.args[4][0]]).to.deep.equal([path, join(path, 'parent.report-meta.xml')]); + expect([isDirSpy.args[7][0], isDirSpy.args[8][0]]).to.deep.equal([ + join(path, 'dir1'), + join(path, 'parent.report-meta.xml'), + ]); + expect([isDirSpy.args[10][0], isDirSpy.args[11][0]]).to.deep.equal([ + join(path, 'dir1'), + join(path, 'dir1', 'dir1.report-meta.xml'), + ]); + }); + it('Should determine type for folder files', () => { const path = xmlInFolder.TYPE_DIRECTORY; const access = testUtil.createMetadataResolver([