Skip to content

Commit 11630ad

Browse files
edrioukCopilotCopilot
authored
Refresh outline view for West Projects after cbuild setup complete (#331)
* Refresh outline view for Wets Projects after cbuild setup complete * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Fix outline refresh after cbuild setup * fix tests --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 55b76b2 commit 11630ad

5 files changed

Lines changed: 115 additions & 4 deletions

File tree

src/solutions/csolution.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { CSolution } from './csolution';
2121
import { ETextFileResult } from '../generic/text-file';
2222
import { CTreeItem } from '../generic/tree-item';
2323
import { parseYamlToCTreeItem } from '../generic/tree-item-yaml-parser';
24+
import { CProjectYamlFile } from './files/cproject-yaml-file';
2425

2526
describe('CSolution', () => {
2627
const testDataHandler = new TestDataHandler();
@@ -621,4 +622,35 @@ describe('CSolution', () => {
621622
});
622623
});
623624
});
625+
626+
describe('hasWestProject', () => {
627+
let csolution: CSolution;
628+
629+
beforeEach(() => {
630+
csolution = new CSolution();
631+
csolution.projects.clear();
632+
});
633+
634+
it('returns true when at least one project is West', () => {
635+
const westProject = { projectType: 'West' } as CProjectYamlFile;
636+
const regularProject = { projectType: 'library' } as CProjectYamlFile;
637+
csolution.projects.set('west', westProject);
638+
csolution.projects.set('lib', regularProject);
639+
640+
expect(csolution.hasWestProject()).toBe(true);
641+
});
642+
643+
it('returns false when no projects are West', () => {
644+
const libProject = { projectType: 'library' } as CProjectYamlFile;
645+
const exeProject = { projectType: 'executable' } as CProjectYamlFile;
646+
csolution.projects.set('lib', libProject);
647+
csolution.projects.set('exe', exeProject);
648+
649+
expect(csolution.hasWestProject()).toBe(false);
650+
});
651+
652+
it('returns false when there are no projects', () => {
653+
expect(csolution.hasWestProject()).toBe(false);
654+
});
655+
});
624656
});

src/solutions/csolution.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,16 @@ export class CSolution {
471471
return this.csolutionYml.compilers;
472472
}
473473

474+
public hasWestProject(): boolean {
475+
for (const project of this.projects.values()) {
476+
if (project?.projectType === 'West') {
477+
return true;
478+
}
479+
}
480+
481+
return false;
482+
}
483+
474484
};
475485

476486
export function expandPath(path: string, csolution?: CSolution, targetType?: string,): string {

src/views/solution-outline/solution-outline.test.ts

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ describe('SolutionOutlineView', () => {
3535
let visibilityChangeEmitter: vscode.EventEmitter<Event>;
3636
let globalStateProvider: GlobalState<CsolutionGlobalState>;
3737
let configurationProvider: MockConfigurationProvider;
38+
let executeCommandSpy: jest.SpyInstance;
3839

3940
beforeEach(async () => {
4041
visibilityChangeEmitter = new vscode.EventEmitter();
@@ -54,6 +55,11 @@ describe('SolutionOutlineView', () => {
5455

5556
globalStateProvider = globalStateFactory();
5657
configurationProvider = configurationProviderFactory();
58+
executeCommandSpy = jest.spyOn(vscode.commands, 'executeCommand').mockResolvedValue(undefined);
59+
});
60+
61+
afterEach(() => {
62+
executeCommandSpy.mockRestore();
5763
});
5864

5965

@@ -214,7 +220,6 @@ describe('SolutionOutlineView', () => {
214220
});
215221

216222
it('reveals the solution outline when a new solution is loaded and auto reveal is enabled', async () => {
217-
const executeCommandSpy = jest.spyOn(vscode.commands, 'executeCommand').mockResolvedValue(undefined);
218223
const solutionLoadedState = activeSolutionLoadStateFactory();
219224
const mockSolutionManager = solutionManagerFactory({
220225
loadState: solutionLoadedState,
@@ -237,11 +242,9 @@ describe('SolutionOutlineView', () => {
237242

238243
expect(executeCommandSpy).toHaveBeenCalledWith(`${SolutionOutlineView.treeViewId}.open`, { preserveFocus: true });
239244

240-
executeCommandSpy.mockRestore();
241245
});
242246

243247
it('does not reveal the solution outline when auto reveal is disabled', async () => {
244-
const executeCommandSpy = jest.spyOn(vscode.commands, 'executeCommand').mockResolvedValue(undefined);
245248
const solutionLoadedState = activeSolutionLoadStateFactory();
246249
const mockSolutionManager = solutionManagerFactory({
247250
loadState: solutionLoadedState,
@@ -267,7 +270,60 @@ describe('SolutionOutlineView', () => {
267270

268271
expect(executeCommandSpy).not.toHaveBeenCalledWith(`${SolutionOutlineView.treeViewId}.open`, { preserveFocus: true });
269272

270-
executeCommandSpy.mockRestore();
273+
});
274+
275+
it('refreshes the tree on compilation database update when a West project exists', async () => {
276+
const solutionLoadedState = activeSolutionLoadStateFactory();
277+
const mockCsolution = csolutionFactory();
278+
mockCsolution.hasWestProject = jest.fn().mockReturnValue(true);
279+
280+
const mockSolutionManager = solutionManagerFactory({
281+
loadState: solutionLoadedState,
282+
getCsolution: jest.fn().mockReturnValue(mockCsolution),
283+
});
284+
285+
const view = new SolutionOutlineView(
286+
mockSolutionManager,
287+
mockTreeViewProvider,
288+
globalStateProvider,
289+
mockTreeViewFileDecorationProvider,
290+
configurationProvider
291+
);
292+
293+
await view.activate(extensionContextFactory());
294+
mockSolutionManager.onUpdatedCompileCommandsEmitter.fire();
295+
await waitForPromises();
296+
297+
expect(mockTreeViewProvider.updateTree).toHaveBeenCalled();
298+
});
299+
300+
it('does not refresh the tree on compilation database update when no West project exists', async () => {
301+
const solutionLoadedState = activeSolutionLoadStateFactory();
302+
const mockCsolution = csolutionFactory();
303+
mockCsolution.hasWestProject = jest.fn().mockReturnValue(false);
304+
305+
const mockSolutionManager = solutionManagerFactory({
306+
loadState: solutionLoadedState,
307+
getCsolution: jest.fn().mockReturnValue(mockCsolution),
308+
});
309+
310+
const view = new SolutionOutlineView(
311+
mockSolutionManager,
312+
mockTreeViewProvider,
313+
globalStateProvider,
314+
mockTreeViewFileDecorationProvider,
315+
configurationProvider
316+
);
317+
318+
await view.activate(extensionContextFactory());
319+
320+
// Reset the mock to ensure it wasn't called during activation
321+
(mockTreeViewProvider.updateTree as jest.Mock).mockClear();
322+
323+
mockSolutionManager.onUpdatedCompileCommandsEmitter.fire();
324+
await waitForPromises();
325+
326+
expect(mockTreeViewProvider.updateTree).not.toHaveBeenCalled();
271327
});
272328

273329
});

src/views/solution-outline/solution-outline.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export class SolutionOutlineView {
4747
this.hasSeen();
4848
}),
4949
this.solutionManager.onDidChangeLoadState(this.handleChangeLoadState, this),
50+
this.solutionManager.onUpdatedCompileCommands(this.handleUpdatedCompileCommands, this),
5051
);
5152
this.treeViewProvider.activate(context);
5253
}
@@ -56,6 +57,16 @@ export class SolutionOutlineView {
5657
this.treeViewProvider.setBadge({ tooltip: '', value: 0 });
5758
}
5859

60+
private async handleUpdatedCompileCommands() {
61+
const csolution = this.solutionManager.getCsolution();
62+
if (!csolution?.hasWestProject()) {
63+
return;
64+
}
65+
66+
await csolution.loadBuildFiles();
67+
await this.updateTree(this.solutionManager.loadState);
68+
}
69+
5970
private async handleChangeLoadState(e: SolutionLoadStateChangeEvent) {
6071
await this.updateTree(e.newState);
6172
if (this.solutionPath !== e.newState.solutionPath) {

src/views/solution-outline/tree-structure/solution-outline-tree.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ describe('CSolution', () => {
8383

8484
const loadResult = await csolution.load(fileName);
8585
expect(loadResult).toEqual(ETextFileResult.Success);
86+
expect(csolution.hasWestProject()).toBeFalsy();
8687

8788
const cdefaultPath = csolution.cbuildIdxFile?.topItem?.getValue('cdefault');
8889
const hasCdefault = !!cdefaultPath && fsUtils.fileExists(
@@ -241,6 +242,7 @@ describe('CSolution', () => {
241242

242243
const loadResult = await csolution.load(fileName);
243244
expect(loadResult).toEqual(ETextFileResult.Success);
245+
expect(csolution.hasWestProject()).toBeTruthy();
244246

245247
// get results from tree
246248
const solutionOutlineTree = new SolutionOutlineTree(csolution, rpcData);

0 commit comments

Comments
 (0)