Skip to content

Commit 775cfac

Browse files
committed
Rearrange RPC calls
1 parent afb381b commit 775cfac

3 files changed

Lines changed: 38 additions & 34 deletions

File tree

src/solutions/solution-manager.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export class SolutionManagerImpl implements SolutionManager {
147147
if (!this.isSolutionActivated()) {
148148
return;
149149
}
150-
if (await this.loadSolution()) {
150+
if (await this.loadSolution(true)) { // some RPC data can change (e.g. different CMSIS_PACK_ROOT)
151151
this.requestConvert(false, true, false);
152152
}
153153
}
@@ -163,7 +163,7 @@ export class SolutionManagerImpl implements SolutionManager {
163163

164164
if (solutionPath) {
165165
this.setLoadState(newState, false);
166-
if (await this.loadSolution()) {
166+
if (await this.loadSolution(true)) { // first load, read RPC data for fast update of the views
167167
// trigger solution convert without RTE update
168168
this.requestConvert(false, false, true);
169169
}
@@ -176,7 +176,7 @@ export class SolutionManagerImpl implements SolutionManager {
176176
if (!this.loadState.solutionPath) {
177177
return;
178178
}
179-
if (await this.loadSolution()) {
179+
if (await this.loadSolution(false)) { // no update RTE before convert
180180
this.requestConvert(true, false, false);
181181
}
182182
}
@@ -217,7 +217,7 @@ export class SolutionManagerImpl implements SolutionManager {
217217
}
218218
}
219219

220-
private async loadSolution(): Promise<boolean> {
220+
private async loadSolution(updateRpcData: boolean): Promise<boolean> {
221221
if (this.loadingSolution || !this.loadState.solutionPath) {
222222
return false;
223223
}
@@ -226,12 +226,15 @@ export class SolutionManagerImpl implements SolutionManager {
226226
this.csolution = new CSolution();
227227
await this.csolution.load(this.loadState.solutionPath);
228228

229+
// read if RPC data if requested
230+
if (updateRpcData) {
231+
await this.updateRpcData();
232+
}
229233
// Create new state object with loaded flag
230234
const newState: SolutionLoadState = {
231235
...this.loadState,
232236
loaded: true
233237
};
234-
await this.updateRpcData();
235238
this.setLoadState(newState, true);
236239
} catch (error) {
237240
console.error(`Failed to load ${this.loadState.solutionPath}`, error);
@@ -245,6 +248,7 @@ export class SolutionManagerImpl implements SolutionManager {
245248
if (!this.csolution) {
246249
return;
247250
}
251+
await this.updateRpcData(); // refresh RPC data
248252
await this.loadSolutionBuildFiles();
249253

250254
if (data.severity != 'error') {

src/views/manage-components-packs/components-packs-webview-main.test.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -597,9 +597,13 @@ describe('ComponentsPacksWebviewMain', () => {
597597

598598
it('performs full reload sequence when reload=true', async () => {
599599
const svc = setupCsolutionServiceMocks();
600+
(componentsPacksWebviewMain as any).currentProject = {
601+
solutionPath: 'solPath',
602+
project: { projectId: 'proj.cproject.yml', projectName: 'proj' }
603+
};
600604
(componentsPacksWebviewMain as any).getActiveContext = jest.fn().mockReturnValue('activeCtx');
601605

602-
await (componentsPacksWebviewMain as any).loadSolution('solPath', 'activeTs', 'activeCtx', true);
606+
await (componentsPacksWebviewMain as any).loadSolution('activeCtx', true);
603607

604608
// Ordering-sensitive state messages (exclude the final undefined clear + others at end)
605609
const stateMessages = webviewManager.sendMessage.mock.calls
@@ -610,16 +614,11 @@ describe('ComponentsPacksWebviewMain', () => {
610614
// Expect the progressive messages in order (final undefined may appear anywhere in array depending on Promise.all)
611615
expect(stateMessages).toEqual(
612616
expect.arrayContaining([
613-
'Connecting to rpc daemon',
614-
'Loading Solution...',
615-
'Retrieving assigned items...'
617+
'Loading Solution data...'
616618
])
617619
);
618-
expect(stateMessages.indexOf('Connecting to rpc daemon')).toBeLessThan(stateMessages.indexOf('Loading Solution...'));
619-
expect(stateMessages.indexOf('Loading Solution...')).toBeLessThan(stateMessages.indexOf('Retrieving assigned items...'));
620620

621621
expect(svc.loadPacks).not.toHaveBeenCalled();
622-
expect(svc.loadSolution).toHaveBeenCalledWith({ solution: 'solPath', activeTarget: 'activeTs' });
623622
expect(svc.getUsedItems).toHaveBeenCalledWith({ context: 'activeCtx' });
624623
expect(svc.getPacksInfo).toHaveBeenCalledWith({ context: 'activeCtx', all: false });
625624
expect(svc.getComponentsTree).toHaveBeenCalledWith({ context: 'activeCtx', all: false });
@@ -636,18 +635,24 @@ describe('ComponentsPacksWebviewMain', () => {
636635

637636
it('skips heavy reload steps when reload=false', async () => {
638637
const svc = setupCsolutionServiceMocks();
638+
(componentsPacksWebviewMain as any).currentProject = {
639+
solutionPath: 'solPath',
640+
project: { projectId: 'proj.cproject.yml', projectName: 'proj' }
641+
};
642+
(componentsPacksWebviewMain as any).getActiveContext = jest.fn().mockReturnValue('activeCtx');
639643

640644
(componentsPacksWebviewMain as any).usedItems = usedItemsReturn;
641-
await (componentsPacksWebviewMain as any).loadSolution('solPath', 'activeTs', 'activeCtx', false);
645+
await (componentsPacksWebviewMain as any).loadSolution('activeCtx', false);
642646

643647
// Heavy operations not called
644648
expect(svc.loadPacks).not.toHaveBeenCalled();
645649
expect(svc.loadSolution).not.toHaveBeenCalled();
646650

647-
// Still refresh tree, usedItems and validations
651+
// Still refresh tree and validations
648652
expect(svc.getComponentsTree).toHaveBeenCalledTimes(1);
649653
expect(svc.validateComponents).toHaveBeenCalledTimes(1);
650-
expect(svc.getUsedItems).toHaveBeenCalled();
654+
// sendDirtyState({ skipApply: true }) still calls isDirty(), which refreshes used items once.
655+
expect(svc.getUsedItems).toHaveBeenCalledWith({ context: 'activeCtx' });
651656

652657
const compTreeMsg = webviewManager.sendMessage.mock.calls.map(c => c[0]).find(m => m.type === 'SOLUTION_LOADED');
653658
expect(compTreeMsg?.componentTree).toBe(componentTreeReturn);
@@ -658,6 +663,10 @@ describe('ComponentsPacksWebviewMain', () => {
658663

659664
it('handles errors and sends error messages', async () => {
660665
const error = new Error('Boom failure');
666+
(componentsPacksWebviewMain as any).currentProject = {
667+
solutionPath: 'solPath',
668+
project: { projectId: 'proj.cproject.yml', projectName: 'proj' }
669+
};
661670
setupCsolutionServiceMocks({
662671
getComponentsTree: jest.fn().mockRejectedValue(error),
663672
getLogMessages: jest.fn().mockResolvedValue({
@@ -667,7 +676,7 @@ describe('ComponentsPacksWebviewMain', () => {
667676
})
668677
});
669678

670-
await (componentsPacksWebviewMain as any).loadSolution('solPath', 'activeTs', 'ctx', true);
679+
await (componentsPacksWebviewMain as any).loadSolution('ctx', true);
671680

672681
// Expect error sequence: SET_COMPONENT_TREE with cleared data & SET_ERROR_MESSAGES with merged messages
673682
const calls = webviewManager.sendMessage.mock.calls.map(c => c[0]);
@@ -1187,35 +1196,35 @@ describe('ComponentsPacksWebviewMain', () => {
11871196
await (componentsPacksWebviewMain as any).load('proj/board.cproject.yml', true);
11881197

11891198
expect(clearSpy).toHaveBeenCalled();
1190-
expect(loadSolutionSpy).toHaveBeenCalledWith('/solutions/app.csolution.yml', 'Debug', 'ctxProj', true);
1199+
expect(loadSolutionSpy).toHaveBeenCalledWith('ctxProj', true);
11911200
expect(sendSelectedProjectSpy).toHaveBeenCalledWith('proj/board.cproject.yml');
11921201
expect((componentsPacksWebviewMain as any).project.project.projectName).toBe('board');
11931202
});
11941203
});
11951204

11961205
describe('loadSolution failure handling', () => {
1197-
it('throws when csolution load fails and surfaces rpc log messages', async () => {
1206+
it('surfaces rpc log messages when loading solution data fails', async () => {
11981207
webviewManager.sendMessage.mockClear();
11991208
(componentsPacksWebviewMain as any).currentProject = { solutionPath: path.join('root', 'solution.csolution.yml'), project: { projectId: 'proj', projectName: 'proj' } };
12001209
(componentsPacksWebviewMain as any).csolutionService = {
12011210
getVersion: jest.fn().mockResolvedValue('1.0.0'),
12021211
loadPacks: jest.fn().mockResolvedValue(undefined),
1203-
loadSolution: jest.fn().mockResolvedValue({ success: false }),
1204-
getUsedItems: jest.fn(),
1212+
loadSolution: jest.fn().mockResolvedValue({ success: true }),
1213+
getUsedItems: jest.fn().mockRejectedValue(new Error('Boom failure')),
12051214
getPacksInfo: jest.fn().mockResolvedValue({ packs: [] }),
12061215
getComponentsTree: jest.fn(),
12071216
validateComponents: jest.fn(),
12081217
getLogMessages: jest.fn().mockResolvedValue({ errors: ['E'], warnings: ['W'], info: ['I'] })
12091218
};
12101219

1211-
await (componentsPacksWebviewMain as any).loadSolution('solPath', 'ts', 'ctx', true);
1220+
await (componentsPacksWebviewMain as any).loadSolution('ctx', true);
12121221

12131222
const errorMessages = webviewManager.sendMessage.mock.calls
12141223
.map(c => c[0])
12151224
.filter(m => m.type === 'SET_ERROR_MESSAGES');
12161225
const lastErrorMessage = errorMessages.at(-1);
12171226
expect(lastErrorMessage).toBeDefined();
1218-
expect(lastErrorMessage?.messages.map((m: any) => m.message)).toEqual(expect.arrayContaining(['Failed loading solution: solPath due to previous errors', 'E', 'W', 'I']));
1227+
expect(lastErrorMessage?.messages.map((m: any) => m.message)).toEqual(expect.arrayContaining(['Boom failure', 'E', 'W', 'I']));
12191228
});
12201229
});
12211230

src/views/manage-components-packs/components-packs-webview-main.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,12 @@ export class ComponentsPacksWebviewMain {
381381
this.currentProject = { solutionPath: csolution.solutionPath, project: createProject(projectId) };
382382
const actx = this.getActiveContext();
383383

384-
const activeTs = csolution.getActiveTargetSetName() ?? '';
385-
await this.loadSolution(csolution.solutionPath, activeTs, actx, reload);
384+
await this.loadSolution(actx, reload);
386385
await this.sendSelectedProject(backToForwardSlashes(projectId));
387386
}
388387
}
389388

390-
private async loadSolution(solutionPath: string, activeTargetSet: string, activeContext: string, reload: boolean): Promise<void> {
389+
private async loadSolution(activeContext: string, reload: boolean): Promise<void> {
391390
await this.webviewManager.sendMessage({ type: 'SET_ERROR_MESSAGES', messages: [] });
392391

393392
// Abort if conversion is still in progress; handleSolutionLoadChange will trigger reload on converted=true
@@ -400,15 +399,7 @@ export class ComponentsPacksWebviewMain {
400399
if (reload) {
401400
this.availablePacksCache = {};
402401
this.unlinkRequests.clear();
403-
await this.webviewManager.sendMessage({ type: 'SET_SOLUTION_STATE', stateMessage: 'Connecting to rpc daemon' });
404-
405-
await this.webviewManager.sendMessage({ type: 'SET_SOLUTION_STATE', stateMessage: 'Loading Solution...' });
406-
const solutionSuccess = await this.csolutionService.loadSolution({ solution: solutionPath, activeTarget: activeTargetSet });
407-
if (!solutionSuccess.success) {
408-
throw new Error(`Failed loading solution: ${solutionPath} due to previous errors`);
409-
}
410-
411-
await this.webviewManager.sendMessage({ type: 'SET_SOLUTION_STATE', stateMessage: 'Retrieving assigned items...' });
402+
await this.webviewManager.sendMessage({ type: 'SET_SOLUTION_STATE', stateMessage: 'Loading Solution data...' });
412403
this.usedItems = await this.csolutionService.getUsedItems({ context: activeContext });
413404
}
414405
await this.webviewManager.sendMessage({ type: 'SET_UNLINKREQUESTS_STACK', unlinkRequests: Array.from(this.unlinkRequests) });

0 commit comments

Comments
 (0)