@@ -3,7 +3,6 @@ import { nls } from '@theia/core/lib/common/nls';
3
3
import { notEmpty } from '@theia/core/lib/common/objects' ;
4
4
import { inject , injectable } from '@theia/core/shared/inversify' ;
5
5
import {
6
- Board ,
7
6
BoardDetails ,
8
7
BoardSearch ,
9
8
BoardUserField ,
@@ -32,11 +31,9 @@ import {
32
31
BoardListAllResponse ,
33
32
BoardSearchRequest ,
34
33
} 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' ;
36
35
import {
37
36
PlatformInstallRequest ,
38
- PlatformListRequest ,
39
- PlatformListResponse ,
40
37
PlatformSearchRequest ,
41
38
PlatformSearchResponse ,
42
39
PlatformUninstallRequest ,
@@ -247,24 +244,22 @@ export class BoardsServiceImpl
247
244
248
245
async getInstalledPlatforms ( ) : Promise < BoardsPackage [ ] > {
249
246
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 ) ;
268
263
}
269
264
270
265
private async handleListBoards (
@@ -287,12 +282,28 @@ export class BoardsServiceImpl
287
282
for ( const board of resp . getBoardsList ( ) ) {
288
283
const platform = board . getPlatform ( ) ;
289
284
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
+ }
291
302
const fqbn = board . getFqbn ( ) || undefined ; // prefer undefined over empty string
292
303
const parsedPlatformId = createPlatformIdentifier ( platformId ) ;
293
304
if ( ! parsedPlatformId ) {
294
305
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`
296
307
) ;
297
308
continue ;
298
309
}
@@ -319,8 +330,8 @@ export class BoardsServiceImpl
319
330
name : board . getName ( ) ,
320
331
fqbn : board . getFqbn ( ) ,
321
332
packageId : parsedPlatformId ,
322
- packageName : platform . getName ( ) ,
323
- manuallyInstalled : platform . getManuallyInstalled ( ) ,
333
+ packageName : release . getName ( ) ,
334
+ manuallyInstalled : metadata . getManuallyInstalled ( ) ,
324
335
} ) ;
325
336
}
326
337
}
@@ -375,89 +386,25 @@ export class BoardsServiceImpl
375
386
const coreClient = await this . coreClient ;
376
387
const { client, instance } = coreClient ;
377
388
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
394
391
const resp = await new Promise < PlatformSearchResponse > (
395
392
( 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
+ ) ;
399
399
}
400
400
) ;
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 ) ;
461
408
return sortComponents ( boardsPackages , boardsPackageSortGroup ) ;
462
409
}
463
410
@@ -624,36 +571,45 @@ function boardsPackageSortGroup(boardsPackage: BoardsPackage): SortGroup {
624
571
return types . join ( '-' ) as SortGroup ;
625
572
}
626
573
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
637
590
}
591
+ const { id, website, maintainer } = summary . metadata ;
638
592
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,
649
595
summary : nls . localize (
650
596
'arduino/component/boardsIncluded' ,
651
597
'Boards included in this package:'
652
598
) ,
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 ( ) ) ,
658
606
} ;
659
607
}
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