1
- import { Mutable } from '@theia/core' ;
2
- import { Defined } from '../types' ;
1
+ import type { Mutable } from '@theia/core/lib/common/types ' ;
2
+ import type { Defined } from '../types' ;
3
3
import { naturalCompare } from '../utils' ;
4
4
import {
5
5
BoardIdentifier ,
@@ -225,11 +225,28 @@ function boardListItemComparator(
225
225
if ( ! isMultiBoardsBoardListItem ( left ) && ! isMultiBoardsBoardListItem ( right ) ) {
226
226
return 1 ;
227
227
}
228
+ // ambiguous boards with a unique board name comes first than other ambiguous ones
229
+ if ( isMultiBoardsBoardListItem ( left ) && isMultiBoardsBoardListItem ( right ) ) {
230
+ const leftUniqueName = findUniqueBoardName ( left ) ;
231
+ const rightUniqueName = findUniqueBoardName ( right ) ;
232
+ if ( leftUniqueName && ! rightUniqueName ) {
233
+ return - 1 ;
234
+ }
235
+ if ( ! leftUniqueName && rightUniqueName ) {
236
+ return 1 ;
237
+ }
238
+ if ( leftUniqueName && rightUniqueName ) {
239
+ return naturalCompare ( leftUniqueName , rightUniqueName ) ;
240
+ }
241
+ }
228
242
229
243
// fallback compare based on the address
230
244
return naturalCompare ( left . port . address , right . port . address ) ;
231
245
}
232
246
247
+ /**
248
+ * What is show in the UI with all the refinements, fallbacks, and tooltips.
249
+ */
233
250
export interface BoardListItemLabels {
234
251
readonly boardLabel : string ;
235
252
readonly boardLabelWithFqbn : string ;
@@ -238,9 +255,11 @@ export interface BoardListItemLabels {
238
255
readonly tooltip : string ;
239
256
}
240
257
241
- export function createBoardListItemLabels (
242
- item : BoardListItem
243
- ) : BoardListItemLabels {
258
+ export interface BoardListItemUI extends BoardListItem {
259
+ readonly labels : BoardListItemLabels ;
260
+ }
261
+
262
+ function createBoardListItemLabels ( item : BoardListItem ) : BoardListItemLabels {
244
263
const { port } = item ;
245
264
const portLabel = port . address ;
246
265
const portProtocol = port . protocol ;
@@ -271,7 +290,11 @@ export function createBoardListItemLabels(
271
290
} ;
272
291
}
273
292
274
- type BoardListItemOrIndex = BoardListItem | number ;
293
+ /**
294
+ * When it's not a `number`, you must use a reference from `BoardList#items` at call-site.
295
+ * More formally, `boardList.items.includes(itemOrIndex)` must be `true`.
296
+ */
297
+ type BoardListItemUIOrIndex = BoardListItemUI | number ;
275
298
276
299
/**
277
300
* A list of boards discovered by the Arduino CLI. With the `board list --watch` gRPC equivalent command,
@@ -282,7 +305,7 @@ export interface BoardList {
282
305
/**
283
306
* All detected ports with zero to many boards and optional inferred information based on historical selection/usage.
284
307
*/
285
- readonly items : readonly BoardListItem [ ] ; // TODO: expose `labels`
308
+ readonly items : readonly BoardListItemUI [ ] ;
286
309
/**
287
310
* A snapshot of the board and port configuration this board list has been initialized with.
288
311
*/
@@ -312,19 +335,10 @@ export interface BoardList {
312
335
Record < 'serial' | 'network' | string , ReturnType < BoardList [ 'ports' ] > >
313
336
> ;
314
337
315
- /**
316
- * What is show in the UI with all the fallbacks and tooltips.
317
- *
318
- * _Notes:_ when the argument is not a number, `boardList.items.includes(itemOrIndex)` must be `true`.
319
- */
320
- labelOf ( itemOrIndex : BoardListItemOrIndex ) : BoardListItemLabels ;
321
-
322
338
/**
323
339
* What's the default action when the argument item is selected in the UI.
324
- *
325
- * _Notes:_ when the argument is not a number, `boardList.items.includes(itemOrIndex)` must be `true`.
326
340
*/
327
- defaultAction ( itemOrIndex : BoardListItemOrIndex ) : BoardListItemAction ;
341
+ defaultAction ( itemOrIndex : BoardListItemUIOrIndex ) : BoardListItemAction ;
328
342
329
343
/**
330
344
* For dumping the current state of board list for debugging purposes.
@@ -356,27 +370,28 @@ export function createBoardList(
356
370
boardsConfig : Readonly < BoardsConfig > = emptyBoardsConfig ( ) ,
357
371
boardListHistory : BoardListHistory = { }
358
372
) : BoardList {
359
- const items : BoardListItem [ ] = [ ] ;
373
+ const items : BoardListItemUI [ ] = [ ] ;
360
374
for ( const detectedPort of Object . values ( detectedPorts ) ) {
361
375
const { port, boards } = detectedPort ;
362
376
// boards with arduino vendor should come first
363
377
boards ?. sort ( boardIdentifierComparator ) ;
364
378
const portKey = Port . keyOf ( port ) ;
365
379
const inferredBoard = boardListHistory [ portKey ] ;
380
+ let item : BoardListItem ;
366
381
if ( ! boards ?. length ) {
367
- let item : BoardListItem | InferredBoardListItem = { port } ;
382
+ let unknownItem : BoardListItem | InferredBoardListItem = { port } ;
368
383
// Infer unrecognized boards from the history
369
384
if ( inferredBoard ) {
370
- item = {
371
- ...item ,
385
+ unknownItem = {
386
+ ...unknownItem ,
372
387
inferredBoard,
373
388
type : 'manually-selected' ,
374
389
} ;
375
390
}
376
- items . push ( item ) ;
391
+ item = unknownItem ;
377
392
} else if ( boards . length === 1 ) {
378
393
const board = boards [ 0 ] ;
379
- let item : BoardListItemWithBoard | InferredBoardListItem = {
394
+ let detectedItem : BoardListItemWithBoard | InferredBoardListItem = {
380
395
port,
381
396
board,
382
397
} ;
@@ -385,30 +400,31 @@ export function createBoardList(
385
400
// ignore the inferred item if it's the same as the discovered board
386
401
! boardIdentifierEquals ( board , inferredBoard )
387
402
) {
388
- item = {
389
- ...item ,
403
+ detectedItem = {
404
+ ...detectedItem ,
390
405
inferredBoard,
391
406
type : 'board-overridden' ,
392
407
} ;
393
408
}
394
- items . push ( item ) ;
409
+ item = detectedItem ;
395
410
} else {
396
- let item : MultiBoardsBoardListItem | InferredBoardListItem = {
411
+ let ambiguousItem : MultiBoardsBoardListItem | InferredBoardListItem = {
397
412
port,
398
413
boards,
399
414
} ;
400
415
if ( inferredBoard ) {
401
- item = {
402
- ...item ,
416
+ ambiguousItem = {
417
+ ...ambiguousItem ,
403
418
inferredBoard,
404
419
type : 'manually-selected' ,
405
420
} ;
406
421
}
407
- items . push ( item ) ;
422
+ item = ambiguousItem ;
408
423
}
424
+ const labels = createBoardListItemLabels ( item ) ;
425
+ items . push ( Object . assign ( item , { labels } ) ) ;
409
426
}
410
427
items . sort ( boardListItemComparator ) ;
411
- const labels = items . map ( createBoardListItemLabels ) ;
412
428
const length = items . length ;
413
429
const findSelectedIndex = ( ) : number => {
414
430
if ( ! isDefinedBoardsConfig ( boardsConfig ) ) {
@@ -521,23 +537,14 @@ export function createBoardList(
521
537
portsOnProtocol . push ( detectedPort ) ;
522
538
}
523
539
const matchItem = allPorts [ allPorts . matchingIndex ] ;
524
- // match index is per all ports, IDE2 needs to adjust it per protocol
540
+ // the cached match index is per all ports. Here , IDE2 needs to adjust the match index per grouped protocol
525
541
if ( matchItem ) {
526
542
const matchProtocol = matchItem . port . protocol ;
527
543
const matchPorts = result [ matchProtocol ] ;
528
544
matchPorts . matchingIndex = matchPorts . indexOf ( matchItem ) ;
529
545
}
530
546
return result ;
531
547
} ,
532
- labelOf ( itemOrIndex ) {
533
- let index : number | undefined = undefined ;
534
- if ( typeof itemOrIndex === 'number' ) {
535
- index = itemOrIndex ;
536
- } else {
537
- index = items . indexOf ( itemOrIndex ) ;
538
- }
539
- return labels [ index ] ;
540
- } ,
541
548
defaultAction ( itemOrIndex ) {
542
549
let item : BoardListItem | undefined = undefined ;
543
550
if ( typeof itemOrIndex === 'number' ) {
@@ -592,7 +599,6 @@ export function createBoardList(
592
599
items,
593
600
selectedIndex,
594
601
boardListHistory,
595
- labels,
596
602
} ,
597
603
null ,
598
604
2
0 commit comments