@@ -10,7 +10,6 @@ import { Disposable } from '@theia/core/lib/common/disposable';
1010import { v4 } from 'uuid' ;
1111import { Unknown } from '../common/nls' ;
1212import {
13- AttachedBoardsChangeEvent ,
1413 AvailablePorts ,
1514 Board ,
1615 NotificationServiceServer ,
@@ -251,57 +250,14 @@ export class BoardDiscovery
251250 return ;
252251 }
253252
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+ ) ;
305261 }
306262 }
307263
@@ -332,6 +288,75 @@ export class BoardDiscovery
332288 } ;
333289 return port ;
334290 }
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+ }
335360}
336361
337362enum EventType {
@@ -356,8 +381,18 @@ namespace EventType {
356381 }
357382 }
358383}
359-
360384interface DetectedPort {
361385 port : Port | undefined ;
362386 boards : Board [ ] ;
363387}
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