@@ -10,7 +10,6 @@ import { Disposable } from '@theia/core/shared/vscode-languageserver-protocol';
1010import { v4 } from 'uuid' ;
1111import { Unknown } from '../common/nls' ;
1212import {
13- AttachedBoardsChangeEvent ,
1413 AvailablePorts ,
1514 Board ,
1615 NotificationServiceServer ,
@@ -78,14 +77,6 @@ export class BoardDiscovery
7877
7978 onStart ( ) : void {
8079 this . start ( ) ;
81- this . onClientDidRefresh ( ( ) => this . restart ( ) ) ;
82- }
83- 84- private async restart ( ) : Promise < void > {
85- this . logger . info ( 'restarting before stop' ) ;
86- await this . stop ( ) ;
87- this . logger . info ( 'restarting after stop' ) ;
88- return this . start ( ) ;
8980 }
9081
9182 onStop ( ) : void {
@@ -259,57 +250,14 @@ export class BoardDiscovery
259250 return ;
260251 }
261252
262- const detectedPort = resp . getPort ( ) ;
263- if ( detectedPort ) {
264- const { port, boards } = this . fromRpc ( detectedPort ) ;
265- if ( ! port ) {
266- if ( ! ! boards . length ) {
267- console . warn (
268- `Could not detect the port, but unexpectedly received discovered boards. This is most likely a bug! Response was: ${ this . toJson (
269- resp
270- ) } `
271- ) ;
272- }
273- return ;
274- }
275- const oldState = deepClone ( this . _availablePorts ) ;
276- const newState = deepClone ( this . _availablePorts ) ;
277- const key = Port . keyOf ( port ) ;
278- 279- if ( eventType === EventType . Add ) {
280- if ( newState [ key ] ) {
281- const [ , knownBoards ] = newState [ key ] ;
282- this . logger . warn (
283- `Port '${ Port . toString (
284- port
285- ) } ' was already available. Known boards before override: ${ JSON . stringify (
286- knownBoards
287- ) } `
288- ) ;
289- }
290- newState [ key ] = [ port , boards ] ;
291- } else if ( eventType === EventType . Remove ) {
292- if ( ! newState [ key ] ) {
293- this . logger . warn (
294- `Port '${ Port . toString ( port ) } ' was not available. Skipping`
295- ) ;
296- return ;
297- }
298- delete newState [ key ] ;
299- }
300- 301- const event : AttachedBoardsChangeEvent = {
302- oldState : {
303- ...AvailablePorts . split ( oldState ) ,
304- } ,
305- newState : {
306- ...AvailablePorts . split ( newState ) ,
307- } ,
308- uploadInProgress : this . uploadInProgress ,
309- } ;
310- 311- this . _availablePorts = newState ;
312- 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+ ) ;
313261 }
314262 }
315263
@@ -340,6 +288,75 @@ export class BoardDiscovery
340288 } ;
341289 return port ;
342290 }
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+ }
343360}
344361
345362enum EventType {
@@ -364,8 +381,18 @@ namespace EventType {
364381 }
365382 }
366383}
367- 368384interface DetectedPort {
369385 port : Port | undefined ;
370386 boards : Board [ ] ;
371387}
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