Skip to content

Commit 95ac4a1

Browse files
author
Akos Kitta
committed
feat: use Arduino CLI 0.36.0-rc.1 APIs
Signed-off-by: Akos Kitta <[email protected]>
1 parent ca779e5 commit 95ac4a1

26 files changed

+6865
-2313
lines changed

Diff for: arduino-ide-extension/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
],
170170
"arduino": {
171171
"arduino-cli": {
172-
"version": "0.35.2"
172+
"version": "0.36.0-rc.1"
173173
},
174174
"arduino-fwuploader": {
175175
"version": "2.4.1"

Diff for: arduino-ide-extension/src/common/protocol/boards-service.ts

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ export interface BoardsService
7575
}): Promise<BoardsPackage | undefined>;
7676
searchBoards({ query }: { query?: string }): Promise<BoardWithPackage[]>;
7777
getInstalledBoards(): Promise<BoardWithPackage[]>;
78+
/**
79+
* Returns with all installed platforms including the manually installed ones.
80+
*/
7881
getInstalledPlatforms(): Promise<BoardsPackage[]>;
7982
getBoardUserFields(options: {
8083
fqbn: string;

Diff for: arduino-ide-extension/src/node/boards-service-impl.ts

+86-130
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { nls } from '@theia/core/lib/common/nls';
33
import { notEmpty } from '@theia/core/lib/common/objects';
44
import { inject, injectable } from '@theia/core/shared/inversify';
55
import {
6-
Board,
76
BoardDetails,
87
BoardSearch,
98
BoardUserField,
@@ -32,11 +31,9 @@ import {
3231
BoardListAllResponse,
3332
BoardSearchRequest,
3433
} from './cli-protocol/cc/arduino/cli/commands/v1/board_pb';
35-
import { Platform } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb';
34+
import { PlatformSummary } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb';
3635
import {
3736
PlatformInstallRequest,
38-
PlatformListRequest,
39-
PlatformListResponse,
4037
PlatformSearchRequest,
4138
PlatformSearchResponse,
4239
PlatformUninstallRequest,
@@ -247,24 +244,22 @@ export class BoardsServiceImpl
247244

248245
async getInstalledPlatforms(): Promise<BoardsPackage[]> {
249246
const { instance, client } = await this.coreClient;
250-
return new Promise<BoardsPackage[]>((resolve, reject) => {
251-
client.platformList(
252-
new PlatformListRequest().setInstance(instance),
253-
(err, response) => {
254-
if (err) {
255-
reject(err);
256-
return;
257-
}
258-
resolve(
259-
response
260-
.getInstalledPlatformsList()
261-
.map((platform, _, installedPlatforms) =>
262-
toBoardsPackage(platform, installedPlatforms)
263-
)
264-
);
265-
}
266-
);
267-
});
247+
const resp = await new Promise<PlatformSearchResponse>(
248+
(resolve, reject) => {
249+
client.platformSearch(
250+
new PlatformSearchRequest()
251+
.setInstance(instance)
252+
.setManuallyInstalled(true), // include core manually installed to the sketchbook
253+
(err, resp) => (err ? reject(err) : resolve(resp))
254+
);
255+
}
256+
);
257+
const searchOutput = resp.getSearchOutputList();
258+
return searchOutput
259+
.map((message) => message.toObject(false))
260+
.filter((summary) => summary.installedVersion) // only installed ones
261+
.map(createBoardsPackage)
262+
.filter(notEmpty);
268263
}
269264

270265
private async handleListBoards(
@@ -287,12 +282,28 @@ export class BoardsServiceImpl
287282
for (const board of resp.getBoardsList()) {
288283
const platform = board.getPlatform();
289284
if (platform) {
290-
const platformId = platform.getId();
285+
const metadata = platform.getMetadata();
286+
if (!metadata) {
287+
console.warn(
288+
`Platform metadata is missing for platform: ${JSON.stringify(
289+
platform.toObject(false)
290+
)}. Skipping`
291+
);
292+
continue;
293+
}
294+
const platformId = metadata.getId();
295+
const release = platform.getRelease();
296+
if (!release) {
297+
console.warn(
298+
`Platform release is missing for platform: ${platformId}. Skipping`
299+
);
300+
continue;
301+
}
291302
const fqbn = board.getFqbn() || undefined; // prefer undefined over empty string
292303
const parsedPlatformId = createPlatformIdentifier(platformId);
293304
if (!parsedPlatformId) {
294305
console.warn(
295-
`Could not create platform identifier from platform ID input: ${platform.getId()}. Skipping`
306+
`Could not create platform identifier from platform ID input: ${platformId}. Skipping`
296307
);
297308
continue;
298309
}
@@ -319,8 +330,8 @@ export class BoardsServiceImpl
319330
name: board.getName(),
320331
fqbn: board.getFqbn(),
321332
packageId: parsedPlatformId,
322-
packageName: platform.getName(),
323-
manuallyInstalled: platform.getManuallyInstalled(),
333+
packageName: release.getName(),
334+
manuallyInstalled: metadata.getManuallyInstalled(),
324335
});
325336
}
326337
}
@@ -375,89 +386,25 @@ export class BoardsServiceImpl
375386
const coreClient = await this.coreClient;
376387
const { client, instance } = coreClient;
377388

378-
const installedPlatformsReq = new PlatformListRequest();
379-
installedPlatformsReq.setInstance(instance);
380-
const installedPlatformsResp = await new Promise<PlatformListResponse>(
381-
(resolve, reject) => {
382-
client.platformList(installedPlatformsReq, (err, resp) => {
383-
!!err ? reject(err) : resolve(resp);
384-
});
385-
}
386-
);
387-
const installedPlatforms =
388-
installedPlatformsResp.getInstalledPlatformsList();
389-
390-
const req = new PlatformSearchRequest();
391-
req.setSearchArgs(options.query || '');
392-
req.setAllVersions(true);
393-
req.setInstance(instance);
389+
// `core search` returns with all platform versions when the command is executed via gRPC or with `--format json`
390+
// The `--all` flag is applicable only when filtering for the human-readable (`--format text`) output of the CLI
394391
const resp = await new Promise<PlatformSearchResponse>(
395392
(resolve, reject) => {
396-
client.platformSearch(req, (err, resp) => {
397-
!!err ? reject(err) : resolve(resp);
398-
});
393+
client.platformSearch(
394+
new PlatformSearchRequest()
395+
.setInstance(instance)
396+
.setSearchArgs(options.query ?? ''),
397+
(err, resp) => (err ? reject(err) : resolve(resp))
398+
);
399399
}
400400
);
401-
const packages = new Map<string, BoardsPackage>();
402-
// We must group the cores by ID, and sort platforms by, first the installed version, then version alphabetical order.
403-
// Otherwise we lose the FQBN information.
404-
const groupedById: Map<string, Platform[]> = new Map();
405-
for (const platform of resp.getSearchOutputList()) {
406-
const id = platform.getId();
407-
const idGroup = groupedById.get(id);
408-
if (idGroup) {
409-
idGroup.push(platform);
410-
} else {
411-
groupedById.set(id, [platform]);
412-
}
413-
}
414-
const installedAwareVersionComparator = (
415-
left: Platform,
416-
right: Platform
417-
) => {
418-
// XXX: we cannot rely on `platform.getInstalled()`, it is always an empty string.
419-
const leftInstalled = !!installedPlatforms.find(
420-
(ip) =>
421-
ip.getId() === left.getId() && ip.getInstalled() === left.getLatest()
422-
);
423-
const rightInstalled = !!installedPlatforms.find(
424-
(ip) =>
425-
ip.getId() === right.getId() &&
426-
ip.getInstalled() === right.getLatest()
427-
);
428-
if (leftInstalled && !rightInstalled) {
429-
return -1;
430-
}
431-
if (!leftInstalled && rightInstalled) {
432-
return 1;
433-
}
434-
435-
const invertedVersionComparator =
436-
Installable.Version.COMPARATOR(left.getLatest(), right.getLatest()) *
437-
-1;
438-
// Higher version comes first.
439-
440-
return invertedVersionComparator;
441-
};
442-
for (const value of groupedById.values()) {
443-
value.sort(installedAwareVersionComparator);
444-
}
445-
446-
for (const value of groupedById.values()) {
447-
for (const platform of value) {
448-
const id = platform.getId();
449-
const pkg = packages.get(id);
450-
if (pkg) {
451-
pkg.availableVersions.push(platform.getLatest());
452-
pkg.availableVersions.sort(Installable.Version.COMPARATOR).reverse();
453-
} else {
454-
packages.set(id, toBoardsPackage(platform, installedPlatforms));
455-
}
456-
}
457-
}
458-
459-
const filter = this.typePredicate(options);
460-
const boardsPackages = [...packages.values()].filter(filter);
401+
const typeFilter = this.typePredicate(options);
402+
const searchOutput = resp.getSearchOutputList();
403+
const boardsPackages = searchOutput
404+
.map((message) => message.toObject(false))
405+
.map(createBoardsPackage)
406+
.filter(notEmpty)
407+
.filter(typeFilter);
461408
return sortComponents(boardsPackages, boardsPackageSortGroup);
462409
}
463410

@@ -624,36 +571,45 @@ function boardsPackageSortGroup(boardsPackage: BoardsPackage): SortGroup {
624571
return types.join('-') as SortGroup;
625572
}
626573

627-
function toBoardsPackage(
628-
platform: Platform,
629-
installedPlatforms: Platform[]
630-
): BoardsPackage {
631-
let installedVersion: string | undefined;
632-
const matchingPlatform = installedPlatforms.find(
633-
(ip) => ip.getId() === platform.getId()
634-
);
635-
if (!!matchingPlatform) {
636-
installedVersion = matchingPlatform.getInstalled();
574+
function createBoardsPackage(
575+
summary: PlatformSummary.AsObject
576+
): BoardsPackage | undefined {
577+
if (!isPlatformSummaryWithMetadata(summary)) {
578+
return undefined;
579+
}
580+
const versionReleaseMap = new Map(summary.releasesMap);
581+
const actualRelease =
582+
versionReleaseMap.get(summary.installedVersion) ??
583+
versionReleaseMap.get(summary.latestVersion);
584+
if (!actualRelease) {
585+
return undefined;
586+
}
587+
const { name, typeList, boardsList, deprecated, compatible } = actualRelease;
588+
if (!compatible) {
589+
return undefined; // never show incompatible platforms
637590
}
591+
const { id, website, maintainer } = summary.metadata;
638592
return {
639-
id: platform.getId(),
640-
name: platform.getName(),
641-
author: platform.getMaintainer(),
642-
availableVersions: [platform.getLatest()],
643-
description: platform
644-
.getBoardsList()
645-
.map((b) => b.getName())
646-
.join(', '),
647-
types: platform.getTypeList(),
648-
deprecated: platform.getDeprecated(),
593+
id,
594+
name,
649595
summary: nls.localize(
650596
'arduino/component/boardsIncluded',
651597
'Boards included in this package:'
652598
),
653-
installedVersion,
654-
boards: platform
655-
.getBoardsList()
656-
.map((b) => <Board>{ name: b.getName(), fqbn: b.getFqbn() }),
657-
moreInfoLink: platform.getWebsite(),
599+
description: boardsList.map(({ name }) => name).join(', '),
600+
boards: boardsList,
601+
types: typeList,
602+
moreInfoLink: website,
603+
author: maintainer,
604+
deprecated,
605+
availableVersions: Array.from(versionReleaseMap.keys()),
658606
};
659607
}
608+
609+
type PlatformSummaryWithMetadata = PlatformSummary.AsObject &
610+
Required<Pick<PlatformSummary.AsObject, 'metadata'>>;
611+
function isPlatformSummaryWithMetadata(
612+
summary: PlatformSummary.AsObject
613+
): summary is PlatformSummaryWithMetadata {
614+
return Boolean(summary.metadata);
615+
}

0 commit comments

Comments
 (0)