Skip to content

Commit 4ce9501

Browse files
Add max depth configuration for Roku project discovery (#1533)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: TwitchBronBron <2544493+TwitchBronBron@users.noreply.github.com> Co-authored-by: Bronley Plumb <bronley@gmail.com>
1 parent 9e13502 commit 4ce9501

4 files changed

Lines changed: 202 additions & 4 deletions

File tree

src/LanguageServer.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,8 @@ describe('LanguageServer', () => {
544544
languageServer: {
545545
enableThreading: false,
546546
enableProjectDiscovery: true,
547-
logLevel: 'info'
547+
logLevel: 'info',
548+
projectDiscoveryMaxDepth: 15
548549
}
549550
}
550551
]);

src/LanguageServer.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,8 @@ export class LanguageServer {
434434
languageServer: {
435435
enableThreading: brightscriptConfig.languageServer?.enableThreading ?? LanguageServer.enableThreadingDefault,
436436
enableProjectDiscovery: brightscriptConfig.languageServer?.enableProjectDiscovery ?? LanguageServer.enableProjectDiscoveryDefault,
437-
logLevel: brightscriptConfig?.languageServer?.logLevel
437+
logLevel: brightscriptConfig?.languageServer?.logLevel,
438+
projectDiscoveryMaxDepth: brightscriptConfig?.languageServer?.projectDiscoveryMaxDepth ?? 15
438439
}
439440
};
440441
})
@@ -825,6 +826,7 @@ export interface BrightScriptClientConfiguration {
825826
enableThreading: boolean;
826827
enableProjectDiscovery: boolean;
827828
logLevel: LogLevel | string;
829+
projectDiscoveryMaxDepth?: number;
828830
};
829831
}
830832

src/lsp/ProjectManager.spec.ts

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,195 @@ describe('ProjectManager', () => {
341341
});
342342
});
343343

344+
describe('maxDepth configuration', () => {
345+
function writeTestFiles(files: Record<string, string>) {
346+
for (const [filePath, content] of Object.entries(files)) {
347+
fsExtra.outputFileSync(`${rootDir}/${filePath}`, content);
348+
}
349+
}
350+
351+
it('respects maxDepth of 1 when discovering projects', async () => {
352+
// Create bsconfig.json files at different depths
353+
writeTestFiles({
354+
'bsconfig.json': '',
355+
'level1/bsconfig.json': '',
356+
'level1/level2/bsconfig.json': '',
357+
'level1/level2/level3/bsconfig.json': ''
358+
});
359+
360+
await manager.syncProjects([{
361+
...workspaceSettings,
362+
languageServer: {
363+
...workspaceSettings.languageServer,
364+
projectDiscoveryMaxDepth: 1
365+
}
366+
}]);
367+
368+
// maxDepth: 1 should find files at depth 0 only
369+
expect(
370+
manager.projects.map(x => x.projectKey).sort()
371+
).to.eql([
372+
s`${rootDir}/bsconfig.json`
373+
]);
374+
});
375+
376+
it('respects maxDepth of 5 when discovering projects', async () => {
377+
// Create bsconfig.json files at different depths
378+
writeTestFiles({
379+
'bsconfig.json': '',
380+
'level1/bsconfig.json': '',
381+
'level1/level2/bsconfig.json': '',
382+
'level1/level2/level3/bsconfig.json': '',
383+
'level1/level2/level3/level4/bsconfig.json': '',
384+
'level1/level2/level3/level4/level5/bsconfig.json': '',
385+
'level1/level2/level3/level4/level5/level6/bsconfig.json': ''
386+
});
387+
388+
await manager.syncProjects([{
389+
...workspaceSettings,
390+
languageServer: {
391+
...workspaceSettings.languageServer,
392+
projectDiscoveryMaxDepth: 5
393+
}
394+
}]);
395+
396+
// maxDepth: 5 should find files at depths 0, 1, 2, 3, 4
397+
expect(
398+
manager.projects.map(x => x.projectKey).sort()
399+
).to.eql([
400+
s`${rootDir}/bsconfig.json`,
401+
s`${rootDir}/level1/bsconfig.json`,
402+
s`${rootDir}/level1/level2/bsconfig.json`,
403+
s`${rootDir}/level1/level2/level3/bsconfig.json`,
404+
s`${rootDir}/level1/level2/level3/level4/bsconfig.json`
405+
]);
406+
});
407+
408+
it('respects maxDepth of 20 when discovering projects', async () => {
409+
// Create bsconfig.json files at different depths, skipping some levels in between
410+
// and proving it stops at level 20 by creating files at level 20 and 21
411+
// Note: depth 20 means the file is in the 20th directory level from root
412+
writeTestFiles({
413+
'bsconfig.json': '',
414+
'level1/bsconfig.json': '',
415+
'level1/level2/level3/level4/level5/bsconfig.json': '',
416+
'level1/level2/level3/level4/level5/level6/level7/level8/level9/level10/level11/level12/level13/level14/level15/level16/level17/level18/level19/bsconfig.json': '',
417+
'level1/level2/level3/level4/level5/level6/level7/level8/level9/level10/level11/level12/level13/level14/level15/level16/level17/level18/level19/level20/bsconfig.json': ''
418+
});
419+
420+
await manager.syncProjects([{
421+
...workspaceSettings,
422+
languageServer: {
423+
...workspaceSettings.languageServer,
424+
projectDiscoveryMaxDepth: 20
425+
}
426+
}]);
427+
428+
// maxDepth: 20 should find file at level 19 (depth 20) but not at level 20 (depth 21)
429+
expect(
430+
manager.projects.map(x => x.projectKey).sort()
431+
).to.eql([
432+
s`${rootDir}/bsconfig.json`,
433+
s`${rootDir}/level1/bsconfig.json`,
434+
s`${rootDir}/level1/level2/level3/level4/level5/bsconfig.json`,
435+
s`${rootDir}/level1/level2/level3/level4/level5/level6/level7/level8/level9/level10/level11/level12/level13/level14/level15/level16/level17/level18/level19/bsconfig.json`
436+
]);
437+
});
438+
439+
it('uses default maxDepth of 15 when no maxDepth is specified', async () => {
440+
// Create bsconfig.json files at different depths, skipping some levels in between
441+
// and proving it stops at level 15 by creating files at level 15 and 16
442+
// Note: depth 15 means the file is in the 15th directory level from root
443+
writeTestFiles({
444+
'bsconfig.json': '',
445+
'level1/bsconfig.json': '',
446+
'level1/level2/level3/level4/level5/bsconfig.json': '',
447+
'level1/level2/level3/level4/level5/level6/level7/level8/level9/level10/level11/level12/level13/level14/bsconfig.json': '',
448+
'level1/level2/level3/level4/level5/level6/level7/level8/level9/level10/level11/level12/level13/level14/level15/bsconfig.json': ''
449+
});
450+
451+
await manager.syncProjects([workspaceSettings]);
452+
453+
// Default maxDepth: 15 should find file at level 14 (depth 15) but not at level 15 (depth 16)
454+
expect(
455+
manager.projects.map(x => x.projectKey).sort()
456+
).to.eql([
457+
s`${rootDir}/bsconfig.json`,
458+
s`${rootDir}/level1/bsconfig.json`,
459+
s`${rootDir}/level1/level2/level3/level4/level5/bsconfig.json`,
460+
s`${rootDir}/level1/level2/level3/level4/level5/level6/level7/level8/level9/level10/level11/level12/level13/level14/bsconfig.json`
461+
]);
462+
});
463+
464+
it('respects maxDepth of 1 when discovering roku projects with manifest files', async () => {
465+
// Create manifest files at different depths
466+
writeTestFiles({
467+
'manifest': '',
468+
'source/main.brs': '',
469+
'level1/manifest': '',
470+
'level1/source/main.brs': '',
471+
'level1/level2/manifest': '',
472+
'level1/level2/source/main.brs': '',
473+
'level1/level2/level3/manifest': '',
474+
'level1/level2/level3/source/main.brs': ''
475+
});
476+
477+
await manager.syncProjects([{
478+
...workspaceSettings,
479+
languageServer: {
480+
...workspaceSettings.languageServer,
481+
projectDiscoveryMaxDepth: 1
482+
}
483+
}]);
484+
485+
// maxDepth: 1 should find projects at depth 0 only
486+
expect(
487+
manager.projects.map(x => x.projectKey).sort()
488+
).to.eql([
489+
s`${rootDir}`
490+
]);
491+
});
492+
493+
it('respects maxDepth of 5 when discovering roku projects with manifest files', async () => {
494+
// Create manifest files at different depths
495+
writeTestFiles({
496+
'manifest': '',
497+
'source/main.brs': '',
498+
'level1/manifest': '',
499+
'level1/source/main.brs': '',
500+
'level1/level2/manifest': '',
501+
'level1/level2/source/main.brs': '',
502+
'level1/level2/level3/manifest': '',
503+
'level1/level2/level3/source/main.brs': '',
504+
'level1/level2/level3/level4/manifest': '',
505+
'level1/level2/level3/level4/source/main.brs': '',
506+
'level1/level2/level3/level4/level5/manifest': '',
507+
'level1/level2/level3/level4/level5/source/main.brs': '',
508+
'level1/level2/level3/level4/level5/level6/manifest': '',
509+
'level1/level2/level3/level4/level5/level6/source/main.brs': ''
510+
});
511+
512+
await manager.syncProjects([{
513+
...workspaceSettings,
514+
languageServer: {
515+
...workspaceSettings.languageServer,
516+
projectDiscoveryMaxDepth: 5
517+
}
518+
}]);
519+
520+
// maxDepth: 5 should find projects at depths 0, 1, 2, 3, 4
521+
expect(
522+
manager.projects.map(x => x.projectKey).sort()
523+
).to.eql([
524+
s`${rootDir}`,
525+
s`${rootDir}/level1`,
526+
s`${rootDir}/level1/level2`,
527+
s`${rootDir}/level1/level2/level3`,
528+
s`${rootDir}/level1/level2/level3/level4`
529+
]);
530+
});
531+
});
532+
344533
describe('getCompletions', () => {
345534
it('works for quick file changes', async () => {
346535
//set up the project

src/lsp/ProjectManager.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,8 @@ export class ProjectManager {
712712
cwd: workspaceConfig.workspaceFolder,
713713
followSymbolicLinks: false,
714714
absolute: true,
715-
onlyFiles: true
715+
onlyFiles: true,
716+
deep: workspaceConfig.languageServer.projectDiscoveryMaxDepth ?? 15
716717
});
717718

718719
//filter the files to only include those that are allowed by the path filterer
@@ -733,7 +734,8 @@ export class ProjectManager {
733734
cwd: workspaceConfig.workspaceFolder,
734735
followSymbolicLinks: false,
735736
absolute: true,
736-
onlyFiles: true
737+
onlyFiles: true,
738+
deep: workspaceConfig.languageServer.projectDiscoveryMaxDepth ?? 15
737739
})).map(async manifestEntry => {
738740
const manifestDir = path.dirname(manifestEntry);
739741
//TODO validate that manifest is a Roku manifest
@@ -949,6 +951,10 @@ export interface WorkspaceConfig {
949951
* The log level to use for this workspace
950952
*/
951953
logLevel?: LogLevel | string;
954+
/**
955+
* Maximum depth to search for Roku projects
956+
*/
957+
projectDiscoveryMaxDepth?: number;
952958
};
953959
}
954960

0 commit comments

Comments
 (0)