Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3093a85

Browse filesBrowse files
author
Akos Kitta
committed
fix: custom board options handling in data store
Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent 9351f5f commit 3093a85
Copy full SHA for 3093a85

File tree

6 files changed

+333
-36
lines changed
Filter options

6 files changed

+333
-36
lines changed

‎arduino-ide-extension/src/browser/boards/boards-data-store.ts

Copy file name to clipboardExpand all lines: arduino-ide-extension/src/browser/boards/boards-data-store.ts
+30-19Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
Programmer,
2222
isBoardIdentifierChangeEvent,
2323
isProgrammer,
24+
sanitizeFqbn,
2425
} from '../../common/protocol';
2526
import { notEmpty } from '../../common/utils';
2627
import type {
@@ -130,7 +131,7 @@ export class BoardsDataStore
130131
if (!fqbn) {
131132
return undefined;
132133
} else {
133-
const data = await this.getData(fqbn);
134+
const data = await this.getData(sanitizeFqbn(fqbn));
134135
if (data === BoardsDataStore.Data.EMPTY) {
135136
return undefined;
136137
}
@@ -228,15 +229,19 @@ export class BoardsDataStore
228229
fqbn: string;
229230
selectedProgrammer: Programmer;
230231
}): Promise<boolean> {
231-
const storedData = deepClone(await this.getData(fqbn));
232+
const sanitizedFQBN = sanitizeFqbn(fqbn);
233+
const storedData = deepClone(await this.getData(sanitizedFQBN));
232234
const { programmers } = storedData;
233235
if (!programmers.find((p) => Programmer.equals(selectedProgrammer, p))) {
234236
return false;
235237
}
236238

237-
const data = { ...storedData, selectedProgrammer };
238-
await this.setData({ fqbn, data });
239-
this.fireChanged({ fqbn, data });
239+
const change: BoardsDataStoreChange = {
240+
fqbn: sanitizedFQBN,
241+
data: { ...storedData, selectedProgrammer },
242+
};
243+
await this.setData(change);
244+
this.fireChanged(change);
240245
return true;
241246
}
242247

@@ -246,24 +251,26 @@ export class BoardsDataStore
246251
return false;
247252
}
248253

249-
const mutableData = deepClone(await this.getData(fqbn));
254+
const sanitizedFQBN = sanitizeFqbn(fqbn);
255+
const mutableData = deepClone(await this.getData(sanitizedFQBN));
250256
let didChange = false;
251257

252258
for (const { option, selectedValue } of optionsToUpdate) {
253259
const { configOptions } = mutableData;
254260
const configOption = configOptions.find((c) => c.option === option);
255261
if (configOption) {
256-
let updated = false;
257-
for (const value of configOption.values) {
258-
const mutable: Mutable<ConfigValue> = value;
259-
if (mutable.value === selectedValue) {
260-
mutable.selected = true;
261-
updated = true;
262-
} else {
263-
mutable.selected = false;
264-
}
265-
}
266-
if (updated) {
262+
const configOptionValueIndex = configOption.values.findIndex(
263+
(configOptionValue) => configOptionValue.value === selectedValue
264+
);
265+
if (configOptionValueIndex >= 0) {
266+
// unselect all
267+
configOption.values
268+
.map((value) => value as Mutable<ConfigValue>)
269+
.forEach((value) => (value.selected = false));
270+
const mutableConfigValue: Mutable<ConfigValue> =
271+
configOption.values[configOptionValueIndex];
272+
// make the new value `selected`
273+
mutableConfigValue.selected = true;
267274
didChange = true;
268275
}
269276
}
@@ -273,8 +280,12 @@ export class BoardsDataStore
273280
return false;
274281
}
275282

276-
await this.setData({ fqbn, data: mutableData });
277-
this.fireChanged({ fqbn, data: mutableData });
283+
const change: BoardsDataStoreChange = {
284+
fqbn: sanitizedFQBN,
285+
data: mutableData,
286+
};
287+
await this.setData(change);
288+
this.fireChanged(change);
278289
return true;
279290
}
280291

‎arduino-ide-extension/src/browser/boards/boards-service-provider.ts

Copy file name to clipboardExpand all lines: arduino-ide-extension/src/browser/boards/boards-service-provider.ts
+40-11Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Emitter } from '@theia/core/lib/common/event';
1212
import { ILogger } from '@theia/core/lib/common/logger';
1313
import { MessageService } from '@theia/core/lib/common/message-service';
1414
import { nls } from '@theia/core/lib/common/nls';
15+
import { deepClone } from '@theia/core/lib/common/objects';
1516
import { Deferred } from '@theia/core/lib/common/promise-util';
1617
import type { Mutable } from '@theia/core/lib/common/types';
1718
import { inject, injectable, optional } from '@theia/core/shared/inversify';
@@ -21,31 +22,32 @@ import {
2122
} from '@theia/output/lib/browser/output-channel';
2223
import {
2324
BoardIdentifier,
24-
boardIdentifierEquals,
25+
BoardUserField,
26+
BoardWithPackage,
2527
BoardsConfig,
2628
BoardsConfigChangeEvent,
2729
BoardsPackage,
2830
BoardsService,
29-
BoardUserField,
30-
BoardWithPackage,
3131
DetectedPorts,
32+
Port,
33+
PortIdentifier,
34+
boardIdentifierEquals,
3235
emptyBoardsConfig,
3336
isBoardIdentifier,
3437
isBoardIdentifierChangeEvent,
3538
isPortIdentifier,
3639
isPortIdentifierChangeEvent,
37-
Port,
38-
PortIdentifier,
3940
portIdentifierEquals,
41+
sanitizeFqbn,
4042
serializePlatformIdentifier,
4143
} from '../../common/protocol';
4244
import {
4345
BoardList,
4446
BoardListHistory,
45-
createBoardList,
4647
EditBoardsConfigActionParams,
47-
isBoardListHistory,
4848
SelectBoardsConfigActionParams,
49+
createBoardList,
50+
isBoardListHistory,
4951
} from '../../common/protocol/board-list';
5052
import type { Defined } from '../../common/types';
5153
import type {
@@ -104,6 +106,21 @@ type BoardListHistoryUpdateResult =
104106
type BoardToSelect = BoardIdentifier | undefined | 'ignore-board';
105107
type PortToSelect = PortIdentifier | undefined | 'ignore-port';
106108

109+
function sanitizeBoardToSelectFQBN(board: BoardToSelect): BoardToSelect {
110+
if (isBoardIdentifier(board)) {
111+
return sanitizeBoardIdentifierFQBN(board);
112+
}
113+
return board;
114+
}
115+
function sanitizeBoardIdentifierFQBN(board: BoardIdentifier): BoardIdentifier {
116+
if (board.fqbn) {
117+
const copy: Mutable<BoardIdentifier> = deepClone(board);
118+
copy.fqbn = sanitizeFqbn(board.fqbn);
119+
return copy;
120+
}
121+
return board;
122+
}
123+
107124
interface UpdateBoardListHistoryParams {
108125
readonly portToSelect: PortToSelect;
109126
readonly boardToSelect: BoardToSelect;
@@ -356,7 +373,8 @@ export class BoardsServiceProvider
356373
portToSelect !== 'ignore-port' &&
357374
!portIdentifierEquals(portToSelect, previousSelectedPort);
358375
const boardDidChangeEvent = boardDidChange
359-
? { selectedBoard: boardToSelect, previousSelectedBoard }
376+
? // The change event must always contain any custom board options. Hence the board to select is not sanitized.
377+
{ selectedBoard: boardToSelect, previousSelectedBoard }
360378
: undefined;
361379
const portDidChangeEvent = portDidChange
362380
? { selectedPort: portToSelect, previousSelectedPort }
@@ -377,11 +395,22 @@ export class BoardsServiceProvider
377395
return false;
378396
}
379397

380-
this.maybeUpdateBoardListHistory({ portToSelect, boardToSelect });
381-
this.maybeUpdateBoardsData({ boardToSelect, reason });
398+
// unlike for the board change event, every persistent state must not contain custom board config options in the FQBN
399+
const sanitizedBoardToSelect = sanitizeBoardToSelectFQBN(boardToSelect);
400+
401+
this.maybeUpdateBoardListHistory({
402+
portToSelect,
403+
boardToSelect: sanitizedBoardToSelect,
404+
});
405+
this.maybeUpdateBoardsData({
406+
boardToSelect: sanitizedBoardToSelect,
407+
reason,
408+
});
382409

383410
if (isBoardIdentifierChangeEvent(event)) {
384-
this._boardsConfig.selectedBoard = event.selectedBoard;
411+
this._boardsConfig.selectedBoard = event.selectedBoard
412+
? sanitizeBoardIdentifierFQBN(event.selectedBoard)
413+
: event.selectedBoard;
385414
}
386415
if (isPortIdentifierChangeEvent(event)) {
387416
this._boardsConfig.selectedPort = event.selectedPort;

‎arduino-ide-extension/src/browser/contributions/ino-language.ts

Copy file name to clipboardExpand all lines: arduino-ide-extension/src/browser/contributions/ino-language.ts
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
BoardsService,
1111
ExecutableService,
1212
isBoardIdentifierChangeEvent,
13+
sanitizeFqbn,
1314
} from '../../common/protocol';
14-
import { FQBN } from 'fqbn';
1515
import {
1616
defaultAsyncWorkers,
1717
maxAsyncWorkers,
@@ -158,11 +158,11 @@ export class InoLanguage extends SketchContribution {
158158
this.notificationCenter.onDidReinitialize(() => forceRestart()),
159159
this.boardDataStore.onDidChange((event) => {
160160
if (this.languageServerFqbn) {
161-
const sanitizedFqbn = new FQBN(this.languageServerFqbn).sanitize();
161+
const sanitizedFQBN = sanitizeFqbn(this.languageServerFqbn);
162162
// The incoming FQBNs might contain custom boards configs, sanitize them before the comparison.
163163
// https://github.com/arduino/arduino-ide/pull/2113#pullrequestreview-1499998328
164-
const matchingChange = event.changes.find((change) =>
165-
new FQBN(change.fqbn).sanitize().equals(sanitizedFqbn)
164+
const matchingChange = event.changes.find(
165+
(change) => sanitizedFQBN === sanitizeFqbn(change.fqbn)
166166
);
167167
const { boardsConfig } = this.boardsServiceProvider;
168168
if (

‎arduino-ide-extension/src/common/protocol/boards-service.ts

Copy file name to clipboardExpand all lines: arduino-ide-extension/src/common/protocol/boards-service.ts
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,15 @@ export namespace Board {
541541
}
542542
}
543543

544+
/**
545+
* Converts the `VENDOR:ARCHITECTURE:BOARD_ID[:MENU_ID=OPTION_ID[,MENU2_ID=OPTION_ID ...]]` FQBN to
546+
* `VENDOR:ARCHITECTURE:BOARD_ID` format.
547+
* See the details of the `{build.fqbn}` entry in the [specs](https://arduino.github.io/arduino-cli/latest/platform-specification/#global-predefined-properties).
548+
*/
549+
export function sanitizeFqbn(fqbn: string): string {
550+
return new FQBN(fqbn).sanitize().toString();
551+
}
552+
544553
export type PlatformIdentifier = Readonly<{ vendorId: string; arch: string }>;
545554
export function createPlatformIdentifier(
546555
board: BoardWithPackage

‎arduino-ide-extension/src/test/browser/board-service-provider.test.ts

Copy file name to clipboardExpand all lines: arduino-ide-extension/src/test/browser/board-service-provider.test.ts
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,36 @@ describe('board-service-provider', () => {
170170
expect(events).deep.equals([expectedEvent]);
171171
});
172172

173+
it('should ignore custom board configs from the FQBN', () => {
174+
boardsServiceProvider['_boardsConfig'] = {
175+
selectedBoard: uno,
176+
selectedPort: unoSerialPort,
177+
};
178+
const events: BoardsConfigChangeEvent[] = [];
179+
toDisposeAfterEach.push(
180+
boardsServiceProvider.onBoardsConfigDidChange((event) =>
181+
events.push(event)
182+
)
183+
);
184+
const mkr1000WithCustomOptions = {
185+
...mkr1000,
186+
fqbn: `${mkr1000.fqbn}:c1=v1`,
187+
};
188+
const didUpdate = boardsServiceProvider.updateConfig(
189+
mkr1000WithCustomOptions
190+
);
191+
expect(didUpdate).to.be.true;
192+
const expectedEvent: BoardIdentifierChangeEvent = {
193+
previousSelectedBoard: uno,
194+
selectedBoard: mkr1000WithCustomOptions, // the even has the custom board options
195+
};
196+
expect(events).deep.equals([expectedEvent]);
197+
// the persisted state does not have the config options property
198+
expect(boardsServiceProvider.boardsConfig.selectedBoard?.fqbn).to.equal(
199+
mkr1000.fqbn
200+
);
201+
});
202+
173203
it('should not update the board if did not change (board identifier)', () => {
174204
boardsServiceProvider['_boardsConfig'] = {
175205
selectedBoard: uno,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.