@@ -10,7 +10,6 @@ import { Disposable } from '@theia/core/lib/common/disposable';
10
10
import { v4 } from 'uuid' ;
11
11
import { Unknown } from '../common/nls' ;
12
12
import {
13
- AttachedBoardsChangeEvent ,
14
13
AvailablePorts ,
15
14
Board ,
16
15
NotificationServiceServer ,
@@ -251,57 +250,14 @@ export class BoardDiscovery
251
250
return ;
252
251
}
253
252
254
- const detectedPort = resp . getPort ( ) ;
255
- if ( detectedPort ) {
256
- const { port, boards } = this . fromRpc ( detectedPort ) ;
257
- if ( ! port ) {
258
- if ( ! ! boards . length ) {
259
- console . warn (
260
- `Could not detect the port, but unexpectedly received discovered boards. This is most likely a bug! Response was: ${ this . toJson (
261
- resp
262
- ) } `
263
- ) ;
264
- }
265
- return ;
266
- }
267
- const oldState = deepClone ( this . _availablePorts ) ;
268
- const newState = deepClone ( this . _availablePorts ) ;
269
- const key = Port . keyOf ( port ) ;
270
-
271
- if ( eventType === EventType . Add ) {
272
- if ( newState [ key ] ) {
273
- const [ , knownBoards ] = newState [ key ] ;
274
- this . logger . warn (
275
- `Port '${ Port . toString (
276
- port
277
- ) } ' was already available. Known boards before override: ${ JSON . stringify (
278
- knownBoards
279
- ) } `
280
- ) ;
281
- }
282
- newState [ key ] = [ port , boards ] ;
283
- } else if ( eventType === EventType . Remove ) {
284
- if ( ! newState [ key ] ) {
285
- this . logger . warn (
286
- `Port '${ Port . toString ( port ) } ' was not available. Skipping`
287
- ) ;
288
- return ;
289
- }
290
- delete newState [ key ] ;
291
- }
292
-
293
- const event : AttachedBoardsChangeEvent = {
294
- oldState : {
295
- ...AvailablePorts . split ( oldState ) ,
296
- } ,
297
- newState : {
298
- ...AvailablePorts . split ( newState ) ,
299
- } ,
300
- uploadInProgress : this . uploadInProgress ,
301
- } ;
302
-
303
- this . _availablePorts = newState ;
304
- this . notificationService . notifyAttachedBoardsDidChange ( event ) ;
253
+ const rpcDetectedPort = resp . getPort ( ) ;
254
+ if ( rpcDetectedPort ) {
255
+ const detectedPort = this . fromRpc ( rpcDetectedPort ) ;
256
+ this . fireSoon ( { detectedPort, eventType } ) ;
257
+ } else if ( resp . getError ( ) ) {
258
+ this . logger . error (
259
+ `Could not extract any detected 'port' from the board list watch response. An 'error' has occurred: ${ resp . getError ( ) } `
260
+ ) ;
305
261
}
306
262
}
307
263
@@ -332,6 +288,75 @@ export class BoardDiscovery
332
288
} ;
333
289
return port ;
334
290
}
291
+
292
+ private fireSoonHandle ?: NodeJS . Timeout ;
293
+ private bufferedEvents : DetectedPortChangeEvent [ ] = [ ] ;
294
+ private fireSoon ( event : DetectedPortChangeEvent ) : void {
295
+ this . bufferedEvents . push ( event ) ;
296
+ clearTimeout ( this . fireSoonHandle ) ;
297
+ this . fireSoonHandle = setTimeout ( ( ) => {
298
+ const prevState = deepClone ( this . availablePorts ) ;
299
+ const newState = this . calculateNewState ( this . bufferedEvents , prevState ) ;
300
+ if ( ! AvailablePorts . sameAs ( prevState , newState ) ) {
301
+ this . _availablePorts = newState ;
302
+ this . notificationService . notifyAttachedBoardsDidChange ( {
303
+ newState : AvailablePorts . split ( newState ) ,
304
+ oldState : AvailablePorts . split ( prevState ) ,
305
+ uploadInProgress : this . uploadInProgress ,
306
+ } ) ;
307
+ }
308
+ this . bufferedEvents . length = 0 ;
309
+ } , 100 ) ;
310
+ }
311
+
312
+ private calculateNewState (
313
+ events : DetectedPortChangeEvent [ ] ,
314
+ prevState : AvailablePorts
315
+ ) : AvailablePorts {
316
+ const newState = deepClone ( prevState ) ;
317
+ for ( const { detectedPort, eventType } of events ) {
318
+ if ( ! DetectedPort . hasPort ( detectedPort ) ) {
319
+ if ( ! ! detectedPort . boards . length ) {
320
+ console . warn (
321
+ `Could not detect the port, but unexpectedly received discovered boards. This is most likely a bug! Detected port was: ${ JSON . stringify (
322
+ detectedPort
323
+ ) } `
324
+ ) ;
325
+ } else {
326
+ console . warn (
327
+ `Could not detect the port. Skipping: ${ JSON . stringify (
328
+ detectedPort
329
+ ) } `
330
+ ) ;
331
+ }
332
+ continue ;
333
+ }
334
+ const { port, boards } = detectedPort ;
335
+ const key = Port . keyOf ( port ) ;
336
+ if ( eventType === EventType . Add ) {
337
+ const alreadyDetectedPort = newState [ key ] ;
338
+ if ( alreadyDetectedPort ) {
339
+ console . warn (
340
+ `Detected a new port that has been already discovered. The old value will be overridden. Old value: ${ JSON . stringify (
341
+ alreadyDetectedPort
342
+ ) } , new value: ${ JSON . stringify ( detectedPort ) } `
343
+ ) ;
344
+ }
345
+ newState [ key ] = [ port , boards ] ;
346
+ } else if ( eventType === EventType . Remove ) {
347
+ const alreadyDetectedPort = newState [ key ] ;
348
+ if ( ! alreadyDetectedPort ) {
349
+ console . warn (
350
+ `Detected a port removal but it has not been discovered. This is most likely a bug! Detected port was: ${ JSON . stringify (
351
+ detectedPort
352
+ ) } `
353
+ ) ;
354
+ }
355
+ delete newState [ key ] ;
356
+ }
357
+ }
358
+ return newState ;
359
+ }
335
360
}
336
361
337
362
enum EventType {
@@ -356,8 +381,18 @@ namespace EventType {
356
381
}
357
382
}
358
383
}
359
-
360
384
interface DetectedPort {
361
385
port : Port | undefined ;
362
386
boards : Board [ ] ;
363
387
}
388
+ namespace DetectedPort {
389
+ export function hasPort (
390
+ detectedPort : DetectedPort
391
+ ) : detectedPort is DetectedPort & { port : Port } {
392
+ return ! ! detectedPort . port ;
393
+ }
394
+ }
395
+ interface DetectedPortChangeEvent {
396
+ detectedPort : DetectedPort ;
397
+ eventType : EventType . Add | EventType . Remove ;
398
+ }
0 commit comments