Skip to content

Commit f2e79c3

Browse files
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
1 parent 90aff65 commit f2e79c3

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

src/convert/transformers/decomposedMetadataTransformer.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export class DecomposedMetadataTransformer extends BaseMetadataTransformer {
4646
component,
4747
children: new ComponentSet([], this.registry),
4848
};
49+
if (component.xml && existing.component && !existing.component.xml) {
50+
// we've already found and created the parent of this component on L~38
51+
// but now we have more information about the parent (xml) that we didn't have before, so add it
52+
existing.component = component;
53+
}
4954
(component.getChildren() ?? []).map((child) => {
5055
existing.children?.add(child);
5156
});

src/resolve/metadataResolver.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,12 @@ export class MetadataResolver {
7676
return components;
7777
}
7878

79-
for (const fsPath of this.tree.readDirectory(dir).map(fnJoin(dir))) {
79+
for (const fsPath of this.tree
80+
.readDirectory(dir)
81+
.map(fnJoin(dir))
82+
// this method isn't truly recursive, we need to sort directories before files so we look as far down as possible
83+
// before finding the parent and returning only it - by sorting, we make it as recursive as possible
84+
.sort(this.sortDirsFirst)) {
8085
if (ignore.has(fsPath)) {
8186
continue;
8287
}
@@ -117,6 +122,15 @@ export class MetadataResolver {
117122
return components.concat(dirQueue.flatMap((d) => this.getComponentsFromPathRecursive(d, inclusiveFilter)));
118123
}
119124

125+
private sortDirsFirst = (a: string, b: string): number => {
126+
if (this.tree.isDirectory(a) && this.tree.isDirectory(b)) {
127+
return 0;
128+
} else if (this.tree.isDirectory(a) && !this.tree.isDirectory(b)) {
129+
return -1;
130+
} else {
131+
return 1;
132+
}
133+
};
120134
private resolveComponent(fsPath: string, isResolvingSource: boolean): SourceComponent | undefined {
121135
if (this.forceIgnore?.denies(fsPath)) {
122136
// don't resolve the component if the path is denied

test/resolve/metadataResolver.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { basename, dirname, join } from 'node:path';
99
import { assert, expect } from 'chai';
1010
import { Messages, SfError } from '@salesforce/core';
1111
import { ensureString } from '@salesforce/ts-types';
12+
import { createSandbox } from 'sinon';
1213
import {
1314
ComponentSet,
1415
MetadataResolver,
@@ -290,6 +291,48 @@ describe('MetadataResolver', () => {
290291
expect(access.getComponentsFromPath(path)).to.deep.equal(xmlInFolder.COMPONENTS);
291292
});
292293

294+
it('should parse dirs before files', () => {
295+
const path = xmlInFolder.COMPONENT_FOLDER_PATH;
296+
const env = createSandbox();
297+
298+
const access = testUtil.createMetadataResolver([
299+
{
300+
dirPath: path,
301+
children: ['dir1', { name: 'parent.report-meta.xml', data: Buffer.from('Some Data') }],
302+
},
303+
{
304+
dirPath: join(path, 'dir1'),
305+
children: [{ name: 'dir1.report-meta.xml', data: Buffer.from('Some Data') }],
306+
},
307+
]);
308+
// @ts-ignore
309+
const isDirSpy = env.spy(access.tree, 'isDirectory');
310+
311+
const componentMappings = xmlInFolder.COMPONENTS.map((c: SourceComponent) => ({
312+
path: ensureString(c.xml),
313+
component: c,
314+
}));
315+
testUtil.stubAdapters([
316+
{
317+
type: registry.types.report,
318+
componentMappings,
319+
allowContent: false,
320+
},
321+
]);
322+
access.getComponentsFromPath(path);
323+
// isDirectory is called a few times during recursive parsing, after debugging
324+
// we only need to verify calls made in succession are called with dirs, and then files
325+
expect([isDirSpy.args[3][0], isDirSpy.args[4][0]]).to.deep.equal([path, join(path, 'parent.report-meta.xml')]);
326+
expect([isDirSpy.args[7][0], isDirSpy.args[8][0]]).to.deep.equal([
327+
join(path, 'dir1'),
328+
join(path, 'parent.report-meta.xml'),
329+
]);
330+
expect([isDirSpy.args[10][0], isDirSpy.args[11][0]]).to.deep.equal([
331+
join(path, 'dir1'),
332+
join(path, 'dir1', 'dir1.report-meta.xml'),
333+
]);
334+
});
335+
293336
it('Should determine type for folder files', () => {
294337
const path = xmlInFolder.TYPE_DIRECTORY;
295338
const access = testUtil.createMetadataResolver([

0 commit comments

Comments
 (0)