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' ;
33import { naturalCompare } from '../utils' ;
44import {
55 BoardIdentifier ,
@@ -225,11 +225,28 @@ function boardListItemComparator(
225225 if ( ! isMultiBoardsBoardListItem ( left ) && ! isMultiBoardsBoardListItem ( right ) ) {
226226 return 1 ;
227227 }
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+ }
228242
229243 // fallback compare based on the address
230244 return naturalCompare ( left . port . address , right . port . address ) ;
231245}
232246
247+ /**
248+ * What is show in the UI with all the refinements, fallbacks, and tooltips.
249+ */
233250export interface BoardListItemLabels {
234251 readonly boardLabel : string ;
235252 readonly boardLabelWithFqbn : string ;
@@ -238,9 +255,11 @@ export interface BoardListItemLabels {
238255 readonly tooltip : string ;
239256}
240257
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 {
244263 const { port } = item ;
245264 const portLabel = port . address ;
246265 const portProtocol = port . protocol ;
@@ -271,7 +290,11 @@ export function createBoardListItemLabels(
271290 } ;
272291}
273292
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 ;
275298
276299/**
277300 * A list of boards discovered by the Arduino CLI. With the `board list --watch` gRPC equivalent command,
@@ -282,7 +305,7 @@ export interface BoardList {
282305 /**
283306 * All detected ports with zero to many boards and optional inferred information based on historical selection/usage.
284307 */
285- readonly items : readonly BoardListItem [ ] ; // TODO: expose `labels`
308+ readonly items : readonly BoardListItemUI [ ] ;
286309 /**
287310 * A snapshot of the board and port configuration this board list has been initialized with.
288311 */
@@ -312,19 +335,10 @@ export interface BoardList {
312335 Record < 'serial' | 'network' | string , ReturnType < BoardList [ 'ports' ] > >
313336 > ;
314337
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-
322338 /**
323339 * 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`.
326340 */
327- defaultAction ( itemOrIndex : BoardListItemOrIndex ) : BoardListItemAction ;
341+ defaultAction ( itemOrIndex : BoardListItemUIOrIndex ) : BoardListItemAction ;
328342
329343 /**
330344 * For dumping the current state of board list for debugging purposes.
@@ -356,27 +370,28 @@ export function createBoardList(
356370 boardsConfig : Readonly < BoardsConfig > = emptyBoardsConfig ( ) ,
357371 boardListHistory : BoardListHistory = { }
358372) : BoardList {
359- const items : BoardListItem [ ] = [ ] ;
373+ const items : BoardListItemUI [ ] = [ ] ;
360374 for ( const detectedPort of Object . values ( detectedPorts ) ) {
361375 const { port, boards } = detectedPort ;
362376 // boards with arduino vendor should come first
363377 boards ?. sort ( boardIdentifierComparator ) ;
364378 const portKey = Port . keyOf ( port ) ;
365379 const inferredBoard = boardListHistory [ portKey ] ;
380+ let item : BoardListItem ;
366381 if ( ! boards ?. length ) {
367- let item : BoardListItem | InferredBoardListItem = { port } ;
382+ let unknownItem : BoardListItem | InferredBoardListItem = { port } ;
368383 // Infer unrecognized boards from the history
369384 if ( inferredBoard ) {
370- item = {
371- ...item ,
385+ unknownItem = {
386+ ...unknownItem ,
372387 inferredBoard,
373388 type : 'manually-selected' ,
374389 } ;
375390 }
376- items . push ( item ) ;
391+ item = unknownItem ;
377392 } else if ( boards . length === 1 ) {
378393 const board = boards [ 0 ] ;
379- let item : BoardListItemWithBoard | InferredBoardListItem = {
394+ let detectedItem : BoardListItemWithBoard | InferredBoardListItem = {
380395 port,
381396 board,
382397 } ;
@@ -385,30 +400,31 @@ export function createBoardList(
385400 // ignore the inferred item if it's the same as the discovered board
386401 ! boardIdentifierEquals ( board , inferredBoard )
387402 ) {
388- item = {
389- ...item ,
403+ detectedItem = {
404+ ...detectedItem ,
390405 inferredBoard,
391406 type : 'board-overridden' ,
392407 } ;
393408 }
394- items . push ( item ) ;
409+ item = detectedItem ;
395410 } else {
396- let item : MultiBoardsBoardListItem | InferredBoardListItem = {
411+ let ambiguousItem : MultiBoardsBoardListItem | InferredBoardListItem = {
397412 port,
398413 boards,
399414 } ;
400415 if ( inferredBoard ) {
401- item = {
402- ...item ,
416+ ambiguousItem = {
417+ ...ambiguousItem ,
403418 inferredBoard,
404419 type : 'manually-selected' ,
405420 } ;
406421 }
407- items . push ( item ) ;
422+ item = ambiguousItem ;
408423 }
424+ const labels = createBoardListItemLabels ( item ) ;
425+ items . push ( Object . assign ( item , { labels } ) ) ;
409426 }
410427 items . sort ( boardListItemComparator ) ;
411- const labels = items . map ( createBoardListItemLabels ) ;
412428 const length = items . length ;
413429 const findSelectedIndex = ( ) : number => {
414430 if ( ! isDefinedBoardsConfig ( boardsConfig ) ) {
@@ -521,23 +537,14 @@ export function createBoardList(
521537 portsOnProtocol . push ( detectedPort ) ;
522538 }
523539 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
525541 if ( matchItem ) {
526542 const matchProtocol = matchItem . port . protocol ;
527543 const matchPorts = result [ matchProtocol ] ;
528544 matchPorts . matchingIndex = matchPorts . indexOf ( matchItem ) ;
529545 }
530546 return result ;
531547 } ,
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- } ,
541548 defaultAction ( itemOrIndex ) {
542549 let item : BoardListItem | undefined = undefined ;
543550 if ( typeof itemOrIndex === 'number' ) {
@@ -592,7 +599,6 @@ export function createBoardList(
592599 items,
593600 selectedIndex,
594601 boardListHistory,
595- labels,
596602 } ,
597603 null ,
598604 2
0 commit comments