Skip to content

Commit 1a4f53f

Browse files
edrioukCopilot
andauthored
Move problems processing to dedicated module (#162)
* Move problems processing to dedicated module * Update src/solutions/solution-problems.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * optimize calculating severity * Update src/solutions/solution-problems.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/solutions/solution-problems.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 9b169de commit 1a4f53f

9 files changed

Lines changed: 536 additions & 314 deletions

src/desktop/extension.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import { CsolutionService } from '../json-rpc/csolution-rpc-client';
8282
import { BuildStopCommand } from '../tasks/build/build-stop-command';
8383
import { ComponentsPacksWebviewMain } from '../views/manage-components-packs/components-packs-webview-main';
8484
import { SolutionConverterImpl } from '../solutions/solution-converter';
85+
import { SolutionProblemsImpl } from '../solutions/solution-problems';
8586
import { EnvironmentManager } from './env-manager';
8687
import { ExtensionApiWrapper } from '../vscode-api/extension-api-wrapper';
8788
import { SerialMonitorApi, Version } from '@microsoft/vscode-serial-monitor-api';
@@ -178,6 +179,7 @@ export const activate = async (context: ExtensionContext): Promise<CsolutionExte
178179
cmsisToolboxManager,
179180
compileCommandsGenerator,
180181
);
182+
const solutionProblems = new SolutionProblemsImpl(solutionManager, eventHub);
181183

182184
const themeProvider = new ThemeProviderImpl();
183185
const statusBar = new StatusBar(solutionManager, cmsisToolboxManager, themeProvider);
@@ -263,6 +265,7 @@ export const activate = async (context: ExtensionContext): Promise<CsolutionExte
263265
runGeneratorCommand.activate(context),
264266
convertMdkToCsolution.activate(context),
265267
solutionConverterImpl.activate(context),
268+
solutionProblems.activate(context),
266269
clangdManager.activate(context),
267270
componentsManager.activate(context),
268271
createSolution.activate(context),

src/solutions/csolution.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ 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, LogMessages } from '../json-rpc/csolution-rpc-client';
31+
import { VariablesConfiguration } from '../json-rpc/csolution-rpc-client';
3232
import { CbuildPackFile } from './files/cbuild-pack-file';
3333

3434
export const targetTypeSchema = new Schema({
@@ -81,9 +81,6 @@ export class CSolution {
8181
// layer configurations
8282
variablesConfigurations?: VariablesConfiguration[] = undefined;
8383

84-
// log messages
85-
logMessages?: LogMessages = undefined;
86-
8784
public get projects() {
8885
return this.csolutionYml.projects;
8986
}
@@ -488,10 +485,6 @@ export class CSolution {
488485
public setVariablesConfigurations(variablesConfigurations: VariablesConfiguration[] | undefined) {
489486
this.variablesConfigurations = variablesConfigurations;
490487
}
491-
492-
public setLogMessages(logMessages: LogMessages | undefined) {
493-
this.logMessages = logMessages;
494-
}
495488
};
496489

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

src/solutions/solution-converter.test.ts

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { expect, it, describe } from '@jest/globals';
1818
import * as path from 'path';
1919
import * as manifest from '../manifest';
2020
import { ExtensionContext } from 'vscode';
21-
import * as vscode from 'vscode';
2221
import { SolutionConverterImpl } from './solution-converter';
2322
import { MockOutputChannelProvider, outputChannelProviderFactory } from '../vscode-api/output-channel-provider.factories';
2423
import { MockConfigurationProvider, configurationProviderFactory } from '../vscode-api/configuration-provider.factories';
@@ -39,6 +38,7 @@ import { getWorkspaceFolder } from '../utils/vscode-utils';
3938
import * as fsUtils from '../utils/fs-utils';
4039
import { ConvertRequestData, SolutionEventHub } from './solution-event-hub';
4140
import { waitTimeout } from '../__test__/test-waits';
41+
import { SolutionProblemsImpl } from './solution-problems';
4242

4343
jest.mock('which', () => jest.fn((cmd) => Promise.resolve(path.join('path', 'to', cmd))));
4444

@@ -72,6 +72,7 @@ describe('SolutionConverter', () => {
7272
let mockCsolutionService: jest.Mocked<ReturnType<typeof csolutionServiceFactory>>;
7373
let convertRequestData: ConvertRequestData;
7474
let completedListener: jest.Mock;
75+
let solutionProblems: SolutionProblemsImpl;
7576

7677
/**
7778
* Helper to wait for N completion events from EventHub
@@ -143,9 +144,11 @@ describe('SolutionConverter', () => {
143144
cmsisToolboxManager,
144145
compileCommandsGenerator,
145146
);
147+
solutionProblems = new SolutionProblemsImpl(solutionManager, eventHub);
146148

147149
initUtils(mockConfigurationProvider, solutionManager);
148150
converter.activate({ subscriptions: [] } as unknown as ExtensionContext);
151+
await solutionProblems.activate({ subscriptions: [] } as unknown as ExtensionContext);
149152

150153
mockCsolutionService.listMissingPacks.mockResolvedValue({ success: true });
151154
mockCsolutionService.convertSolution.mockResolvedValue({ success: true });
@@ -304,9 +307,6 @@ describe('SolutionConverter', () => {
304307
});
305308

306309
it('get log messages and set diagnostics accordingly', async () => {
307-
const mockDiagnosticsCollectionSet = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'set');
308-
const mockDiagnosticsCollectionClear = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'clear');
309-
310310
mockCsolutionService.convertSolution.mockResolvedValue({ success: false });
311311
mockCsolutionService.getLogMessages.mockResolvedValue({
312312
success: true,
@@ -316,13 +316,10 @@ describe('SolutionConverter', () => {
316316
});
317317
await fireAndWaitForConversion();
318318

319-
expect(mockDiagnosticsCollectionClear).toHaveBeenCalled();
320-
expect(mockDiagnosticsCollectionSet).toHaveBeenCalledTimes(3);
321319
expect(completedListener).toHaveBeenCalledTimes(1);
322320
});
323321

324322
it('get cbuild west output and set diagnostics accordingly', async () => {
325-
const mockDiagnosticsCollectionSet = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'set');
326323
mockCsolutionService.convertSolution.mockResolvedValue({ success: true });
327324
mockCsolutionService.getLogMessages.mockResolvedValue({ success: true });
328325
let mockRunCbuildSetup = jest.spyOn(compileCommandsGenerator, 'runCbuildSetup').mockResolvedValue([true, [
@@ -336,15 +333,23 @@ describe('SolutionConverter', () => {
336333
jest.spyOn(vscodeUtils, 'getWorkspaceFolder').mockReturnValue('workspace/folder');
337334

338335
await fireAndWaitForConversion();
336+
await waitTimeout();
339337
expect(mockRunCbuildSetup).toHaveBeenCalledTimes(1);
340-
expect(mockDiagnosticsCollectionSet).toHaveBeenCalledTimes(2);
341338
expect(completedListener).toHaveBeenCalledTimes(1);
339+
expect(completedListener).toHaveBeenLastCalledWith(
340+
expect.objectContaining({
341+
severity: 'error',
342+
toolsOutputMessages: expect.arrayContaining([
343+
'warning cbuild: missing ZEPHYR_BASE environment variable',
344+
'error cbuild: exec: "west": executable file not found in $PATH',
345+
]),
346+
}),
347+
);
342348

343349
// Remove settings.json
344350
completedListener.mockClear();
345351
const settings = path.join(getWorkspaceFolder(), '.vscode', 'settings.json');
346352
mockRunCbuildSetup.mockClear();
347-
mockDiagnosticsCollectionSet.mockClear();
348353
fsUtils.deleteFileIfExists(settings);
349354
await fireAndWaitForConversion();
350355
expect(mockRunCbuildSetup).toHaveBeenCalledTimes(1);
@@ -354,7 +359,6 @@ describe('SolutionConverter', () => {
354359
completedListener.mockClear();
355360
mockRunCbuildSetup = jest.spyOn(compileCommandsGenerator, 'runCbuildSetup').mockResolvedValue([true, []]);
356361
mockRunCbuildSetup.mockClear();
357-
mockDiagnosticsCollectionSet.mockClear();
358362
await fireAndWaitForConversion();
359363
expect(mockRunCbuildSetup).toHaveBeenCalledTimes(1);
360364
expect(completedListener).toHaveBeenCalledTimes(1);
@@ -425,11 +429,7 @@ describe('SolutionConverter', () => {
425429
});
426430
});
427431

428-
it('creates diagnostic when cpackget fails to download a pack', async () => {
429-
const diagnosticCollection = vscode.languages.createDiagnosticCollection();
430-
const mockDiagnosticsCollectionSet = jest.spyOn(diagnosticCollection, 'set') as unknown as jest.MockedFunction<
431-
(uri: vscode.Uri, diagnostics: readonly vscode.Diagnostic[] | undefined) => void
432-
>;
432+
it('reports error severity when cpackget fails to download a pack', async () => {
433433
jest.spyOn(cmsisToolboxManager, 'runCmsisTool').mockImplementation(async (_t, _a, onOutput) => {
434434
onOutput('W: retry failed');
435435
onOutput('E: network timeout');
@@ -440,24 +440,16 @@ describe('SolutionConverter', () => {
440440

441441
await fireAndWaitForConversion();
442442

443-
expect(mockDiagnosticsCollectionSet).toHaveBeenCalledTimes(1);
444-
const [[, diagnostics]] = mockDiagnosticsCollectionSet.mock.calls;
445-
expect(diagnostics?.[0]?.message).toContain('network timeout');
446-
expect(diagnostics?.[0]?.message).toContain('retry failed');
443+
expect(completedListener).toHaveBeenCalledWith(
444+
expect.objectContaining({
445+
severity: 'error',
446+
toolsOutputMessages: expect.arrayContaining([
447+
expect.stringContaining("error cpackget: downloading pack 'VendorA::PackA@1.0.0' failed"),
448+
expect.stringContaining('network timeout'),
449+
expect.stringContaining('retry failed'),
450+
]),
451+
})
452+
);
447453
});
448454

449-
it('extracts warnings from cbuild2cmake and csolution tool output', async () => {
450-
const mockDiagnosticsCollectionSet = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'set');
451-
mockCsolutionService.convertSolution.mockResolvedValue({ success: true });
452-
mockCsolutionService.getLogMessages.mockResolvedValue({ success: true });
453-
jest.spyOn(compileCommandsGenerator, 'runCbuildSetup').mockResolvedValue([true, [
454-
'warning cbuild2cmake: some warning',
455-
'error csolution: some error',
456-
]]);
457-
458-
await fireAndWaitForConversion();
459-
460-
// Expect two calls: one for cbuild2cmake warning, one for csolution error
461-
expect(mockDiagnosticsCollectionSet).toHaveBeenCalledTimes(2);
462-
});
463455
});

0 commit comments

Comments
 (0)