Skip to content

Commit 3ab97a1

Browse files
edrioukCopilot
andauthored
Refactor manage Layers (#166)
* Refactor manage Layers * resolve merge conflict * Address copilot suggestions * unit tests for the view * Update src/views/manage-layers/manage-layers-webview-main.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/views/manage-layers/manage-layers-webview-main.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/views/manage-layers/manage-layers-webview-main.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * lint --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 2fe9800 commit 3ab97a1

8 files changed

Lines changed: 378 additions & 131 deletions

src/desktop/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ export const activate = async (context: ExtensionContext): Promise<CsolutionExte
172172
const compileCommandsGenerator = new CompileCommandsGeneratorImpl(buildTaskProvider, buildTaskDefinitionBuilder);
173173

174174
const solutionConverterImpl = new SolutionConverterImpl(
175-
solutionManager,
176175
eventHub,
177176
configurationProvider,
178177
outputChannelProvider,
@@ -207,6 +206,7 @@ export const activate = async (context: ExtensionContext): Promise<CsolutionExte
207206
commandsProvider,
208207
messageProvider,
209208
solutionManager,
209+
eventHub,
210210
);
211211

212212
const debugProvider = new DebugLaunchProvider(commandsProvider, solutionManager, configurationProvider);

src/solutions/csolution.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import { ContextDescriptor, contextDescriptorFromString } from './descriptors/de
2828
import { CmsisSettingsJsonFile } from '../global/cmsis-settings-json-file';
2929
import { CSolutionYamlFile } from './files/csolution-yaml-file';
3030
import { CProjectYamlFile } from './files/cproject-yaml-file';
31-
import { VariablesConfiguration } from '../json-rpc/csolution-rpc-client';
3231
import { CbuildPackFile } from './files/cbuild-pack-file';
3332

3433
export const targetTypeSchema = new Schema({
@@ -75,12 +74,6 @@ export class CSolution {
7574
cbuildSetYmlFileName = '';
7675
cmsisJsonFile = new CmsisSettingsJsonFile();
7776

78-
// select-compiler
79-
selectCompiler?: string[] = undefined;
80-
81-
// layer configurations
82-
variablesConfigurations?: VariablesConfiguration[] = undefined;
83-
8477
public get projects() {
8578
return this.csolutionYml.projects;
8679
}
@@ -478,13 +471,6 @@ export class CSolution {
478471
return this.csolutionYml.compilers;
479472
}
480473

481-
public setSelectCompiler(compilers: string[] | undefined) {
482-
this.selectCompiler = compilers;
483-
}
484-
485-
public setVariablesConfigurations(variablesConfigurations: VariablesConfiguration[] | undefined) {
486-
this.variablesConfigurations = variablesConfigurations;
487-
}
488474
};
489475

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

src/solutions/solution-converter.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ describe('SolutionConverter', () => {
108108
eventHub = new SolutionEventHub();
109109
completedListener = jest.fn();
110110
eventHub.onDidConvertCompleted(completedListener);
111+
jest.spyOn(eventHub, 'fireConfigureSolutionDataReady');
111112

112113
// Initialize convertRequestData with default test values
113114
convertRequestData = {
@@ -137,7 +138,6 @@ describe('SolutionConverter', () => {
137138
solutionManager.getCsolution.mockReturnValue(mockCSolution);
138139

139140
converter = new SolutionConverterImpl(
140-
solutionManager,
141141
eventHub,
142142
mockConfigurationProvider,
143143
outputChannelProvider,
@@ -281,6 +281,7 @@ describe('SolutionConverter', () => {
281281

282282
it('run solution convert and discover layers', async () => {
283283
mockCsolutionService.convertSolution.mockResolvedValue({ success: false, undefinedLayers: ['$Board-Layer'] });
284+
mockCsolutionService.discoverLayers.mockResolvedValue({ success: true, configurations: [{ variables: [] }] });
284285
await fireAndWaitForConversion();
285286

286287
expect(mockCsolutionService.discoverLayers).toHaveBeenCalledTimes(1);
@@ -291,6 +292,29 @@ describe('SolutionConverter', () => {
291292
detection: true
292293
})
293294
);
295+
expect(eventHub.fireConfigureSolutionDataReady).toHaveBeenCalledTimes(1);
296+
expect(eventHub.fireConfigureSolutionDataReady).toHaveBeenCalledWith(
297+
expect.objectContaining({
298+
availableCompilers: [],
299+
availableConfigurations: [{ variables: [] }],
300+
})
301+
);
302+
});
303+
304+
it('emits configure event with compilers when selectCompiler is returned', async () => {
305+
mockCsolutionService.convertSolution.mockResolvedValue({ success: true, selectCompiler: ['GCC', 'AC6'] });
306+
await fireAndWaitForConversion();
307+
308+
expect(completedListener).toHaveBeenCalledWith(
309+
expect.objectContaining({ detection: true })
310+
);
311+
expect(eventHub.fireConfigureSolutionDataReady).toHaveBeenCalledTimes(1);
312+
expect(eventHub.fireConfigureSolutionDataReady).toHaveBeenCalledWith(
313+
expect.objectContaining({
314+
availableCompilers: ['GCC', 'AC6'],
315+
availableConfigurations: undefined,
316+
})
317+
);
294318
});
295319

296320
it('reports discoverLayers failure through toolsOutputMessages', async () => {

src/solutions/solution-converter.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import * as manifest from '../manifest';
1919
import { ConfigurationProvider } from '../vscode-api/configuration-provider';
2020
import { OutputChannelProvider } from '../vscode-api/output-channel-provider';
2121
import { CmsisToolboxManager } from './cmsis-toolbox';
22-
import { SolutionManager } from './solution-manager';
2322
import { CompileCommandsGenerator } from './intellisense/compile-commands-generator';
2423
import { Mutex } from 'async-mutex';
2524
import * as rpc from '../json-rpc/csolution-rpc-client';
@@ -39,7 +38,6 @@ export class SolutionConverterImpl implements SolutionConverter {
3938
private data: ConvertRequestData = { solutionPath: '', targetSet: '', updateRte: false, restartRpc: false };
4039

4140
constructor(
42-
private readonly solutionManager: SolutionManager,
4341
private readonly eventHub: SolutionEventHub,
4442
private readonly configProvider: ConfigurationProvider,
4543
private readonly outputChannelProvider: OutputChannelProvider,
@@ -143,7 +141,8 @@ export class SolutionConverterImpl implements SolutionConverter {
143141

144142
let detection = false;
145143
let convertResult: rpc.ConvertSolutionResult = { success: false };
146-
const csolution = this.solutionManager.getCsolution();
144+
let availableCompilers: string[] = [];
145+
let availableConfigurations: rpc.VariablesConfiguration[] | undefined;
147146
if (!missingPacksResult || missingPacksResult.success) {
148147
// rpc method: ConvertSolution
149148
outputChannel.append('Convert solution... ');
@@ -160,14 +159,16 @@ export class SolutionConverterImpl implements SolutionConverter {
160159
return;
161160
}
162161

163-
// compilers and variables detection handling: apply select-compiler and discover layer configurations if any
164-
csolution?.setSelectCompiler(convertResult.selectCompiler);
162+
// compilers and variables detection: gather locally and emit configure event
163+
availableCompilers = convertResult.selectCompiler ?? [];
164+
detection = availableCompilers.length > 0;
165165
if (convertResult.undefinedLayers) {
166-
const [discoverLayersDetected, discoverLayersOutput] = await this.checkDiscoverLayers();
167-
detection = discoverLayersDetected;
166+
const result = await this.checkDiscoverLayers();
167+
const discoverLayersOutput = !result.success && result.message ? [`error csolution: ${result.message.trim()}`] : [];
168168
toolsOutputMessages = toolsOutputMessages.concat(discoverLayersOutput);
169+
availableConfigurations = result.configurations;
170+
detection = detection || result.success;
169171
}
170-
detection = detection || !!convertResult.selectCompiler;
171172
}
172173

173174
let logResult = undefined;
@@ -212,6 +213,10 @@ export class SolutionConverterImpl implements SolutionConverter {
212213
logMessages: logResult,
213214
toolsOutputMessages,
214215
});
216+
// compilers and variables detection handling:
217+
// apply select-compiler and discover layer configurations, reset state otherwise
218+
this.eventHub.fireConfigureSolutionDataReady({ availableCompilers, availableConfigurations });
219+
215220
}
216221

217222
private async printErrorsWarnings(messages?: rpc.LogMessages): Promise<void> {
@@ -249,9 +254,8 @@ export class SolutionConverterImpl implements SolutionConverter {
249254
return formattedOutput;
250255
}
251256

252-
private async checkDiscoverLayers(): Promise<[boolean, string[]]> {
257+
private async checkDiscoverLayers() {
253258
const outputChannel = this.outputChannelProvider.getOrCreate(manifest.CMSIS_SOLUTION_OUTPUT_CHANNEL);
254-
this.solutionManager.getCsolution()?.setVariablesConfigurations(undefined);
255259
// rpc method: DiscoverLayers
256260
outputChannel.append('Discover Layers... ');
257261
const result = await this.cmsisToolboxManager.runCsolutionRpc(
@@ -261,9 +265,7 @@ export class SolutionConverterImpl implements SolutionConverter {
261265
activeTarget: this.data?.targetSet ?? '',
262266
}
263267
) as rpc.DiscoverLayersInfo;
264-
this.solutionManager.getCsolution()?.setVariablesConfigurations(result.configurations);
265-
const formattedOutput = !result.success && result.message ? [`error csolution: ${result.message.trim()}`] : [];
266-
return [result.success, formattedOutput];
268+
return result;
267269
}
268270

269271
private getSeverity(messages: rpc.LogMessages, lines?: string[]): Severity {

src/solutions/solution-event-hub.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('EventHub', () => {
3434
it('should register emitters with context subscriptions', async () => {
3535
await eventHub.activate(mockContext);
3636

37-
expect(mockContext.subscriptions).toHaveLength(2);
37+
expect(mockContext.subscriptions).toHaveLength(3);
3838
});
3939
});
4040

@@ -178,4 +178,30 @@ describe('EventHub', () => {
178178
expect(listener).toHaveBeenCalledTimes(2);
179179
});
180180
});
181+
182+
describe('fireConfigureSolutionDataReady', () => {
183+
it('should fire event with compilers and configurations', async () => {
184+
const listener = jest.fn();
185+
eventHub.onDidConfigureSolutionDataReady(listener);
186+
187+
const data = { availableCompilers: ['GCC', 'AC6'], availableConfigurations: undefined };
188+
await eventHub.fireConfigureSolutionDataReady(data);
189+
190+
expect(listener).toHaveBeenCalledTimes(1);
191+
expect(listener).toHaveBeenCalledWith(data);
192+
});
193+
194+
it('should notify multiple listeners', async () => {
195+
const listener1 = jest.fn();
196+
const listener2 = jest.fn();
197+
eventHub.onDidConfigureSolutionDataReady(listener1);
198+
eventHub.onDidConfigureSolutionDataReady(listener2);
199+
200+
const data = { availableCompilers: [], availableConfigurations: [{ variables: [] }] };
201+
await eventHub.fireConfigureSolutionDataReady(data);
202+
203+
expect(listener1).toHaveBeenCalledWith(data);
204+
expect(listener2).toHaveBeenCalledWith(data);
205+
});
206+
});
181207
});

src/solutions/solution-event-hub.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
import * as vscode from 'vscode';
1717
import { constructor } from '../generic/constructor';
18-
import { LogMessages } from '../json-rpc/csolution-rpc-client';
18+
import { LogMessages, VariablesConfiguration } from '../json-rpc/csolution-rpc-client';
1919
import { Severity } from './constants';
2020

2121
/**
@@ -29,6 +29,14 @@ export interface ConvertRequestData {
2929
lockAbort?: boolean;
3030
}
3131

32+
/**
33+
* Event data for configure solution readiness
34+
*/
35+
export interface ConfigureSolutionData {
36+
availableCompilers: string[];
37+
availableConfigurations: VariablesConfiguration[] | undefined;
38+
}
39+
3240
/**
3341
* Event data for solution conversion result
3442
*/
@@ -69,6 +77,14 @@ export interface SolutionEventHub {
6977
* Event fired when solution conversion is completed
7078
*/
7179
readonly onDidConvertCompleted: vscode.Event<ConvertResultData>;
80+
/**
81+
* Fire configure solution data ready event
82+
*/
83+
fireConfigureSolutionDataReady(data: ConfigureSolutionData): Promise<void>;
84+
/**
85+
* Event fired when configure solution data is ready (compilers / layer configurations detected)
86+
*/
87+
readonly onDidConfigureSolutionDataReady: vscode.Event<ConfigureSolutionData>;
7288
}
7389

7490
class SolutionEventHubImpl {
@@ -79,9 +95,13 @@ class SolutionEventHubImpl {
7995
private readonly convertCompleteEmitter = new vscode.EventEmitter<ConvertResultData>();
8096
public readonly onDidConvertCompleted: vscode.Event<ConvertResultData> = this.convertCompleteEmitter.event;
8197

98+
private readonly configureSolutionDataEmitter = new vscode.EventEmitter<ConfigureSolutionData>();
99+
public readonly onDidConfigureSolutionDataReady: vscode.Event<ConfigureSolutionData> = this.configureSolutionDataEmitter.event;
100+
82101
public async activate(context: vscode.ExtensionContext): Promise<void> {
83102
context.subscriptions.push(this.convertRequestEmitter);
84103
context.subscriptions.push(this.convertCompleteEmitter);
104+
context.subscriptions.push(this.configureSolutionDataEmitter);
85105
}
86106

87107
public async fireConvertRequest(data: ConvertRequestData): Promise<void> {
@@ -91,6 +111,10 @@ class SolutionEventHubImpl {
91111
public async fireConvertCompleted(data: ConvertResultData): Promise<void> {
92112
this.convertCompleteEmitter.fire(data);
93113
}
114+
115+
public async fireConfigureSolutionDataReady(data: ConfigureSolutionData): Promise<void> {
116+
this.configureSolutionDataEmitter.fire(data);
117+
}
94118
}
95119

96120
export const SolutionEventHub = constructor<typeof SolutionEventHubImpl, SolutionEventHub>(SolutionEventHubImpl);

0 commit comments

Comments
 (0)