19
19
import * as React from '@theia/core/shared/react' ;
20
20
import { LabelProvider } from '@theia/core/lib/browser' ;
21
21
import { DebugProtocol } from 'vscode-debugprotocol' ;
22
- import { Emitter , Event , DisposableCollection , Disposable , MessageClient , MessageType , Mutable } from '@theia/core/lib/common' ;
22
+ import { Emitter , Event , DisposableCollection , Disposable , MessageClient , MessageType , Mutable , ContributionProvider } from '@theia/core/lib/common' ;
23
23
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service' ;
24
24
import { EditorManager } from '@theia/editor/lib/browser' ;
25
25
import { CompositeTreeElement } from '@theia/core/lib/browser/source-tree' ;
@@ -39,6 +39,7 @@ import { SourceBreakpoint, ExceptionBreakpoint } from './breakpoint/breakpoint-m
39
39
import { TerminalWidgetOptions , TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget' ;
40
40
import { DebugFunctionBreakpoint } from './model/debug-function-breakpoint' ;
41
41
import { FileService } from '@theia/filesystem/lib/browser/file-service' ;
42
+ import { DebugContribution } from './debug-contribution' ;
42
43
43
44
export enum DebugState {
44
45
Inactive ,
@@ -49,7 +50,6 @@ export enum DebugState {
49
50
50
51
// FIXME: make injectable to allow easily inject services
51
52
export class DebugSession implements CompositeTreeElement {
52
-
53
53
protected readonly onDidChangeEmitter = new Emitter < void > ( ) ;
54
54
readonly onDidChange : Event < void > = this . onDidChangeEmitter . event ;
55
55
protected fireDidChange ( ) : void {
@@ -73,8 +73,12 @@ export class DebugSession implements CompositeTreeElement {
73
73
protected readonly breakpoints : BreakpointManager ,
74
74
protected readonly labelProvider : LabelProvider ,
75
75
protected readonly messages : MessageClient ,
76
- protected readonly fileService : FileService ) {
76
+ protected readonly fileService : FileService ,
77
+ protected readonly debugContributionProvider : ContributionProvider < DebugContribution >
78
+ ) {
77
79
this . connection . onRequest ( 'runInTerminal' , ( request : DebugProtocol . RunInTerminalRequest ) => this . runInTerminal ( request ) ) ;
80
+ this . registerDebugContributions ( options . configuration . type , this . connection ) ;
81
+
78
82
this . toDispose . pushAll ( [
79
83
this . onDidChangeEmitter ,
80
84
this . onDidChangeBreakpointsEmitter ,
@@ -115,9 +119,11 @@ export class DebugSession implements CompositeTreeElement {
115
119
this . sources . set ( uri , source ) ;
116
120
return source ;
117
121
}
122
+
118
123
getSourceForUri ( uri : URI ) : DebugSource | undefined {
119
124
return this . sources . get ( uri . toString ( ) ) ;
120
125
}
126
+
121
127
async toSource ( uri : URI ) : Promise < DebugSource > {
122
128
const source = this . getSourceForUri ( uri ) ;
123
129
if ( source ) {
@@ -149,19 +155,23 @@ export class DebugSession implements CompositeTreeElement {
149
155
get threads ( ) : IterableIterator < DebugThread > {
150
156
return this . _threads . values ( ) ;
151
157
}
158
+
152
159
get threadCount ( ) : number {
153
160
return this . _threads . size ;
154
161
}
162
+
155
163
* getThreads ( filter : ( thread : DebugThread ) => boolean ) : IterableIterator < DebugThread > {
156
164
for ( const thread of this . threads ) {
157
165
if ( filter ( thread ) ) {
158
166
yield thread ;
159
167
}
160
168
}
161
169
}
170
+
162
171
get runningThreads ( ) : IterableIterator < DebugThread > {
163
172
return this . getThreads ( thread => ! thread . stopped ) ;
164
173
}
174
+
165
175
get stoppedThreads ( ) : IterableIterator < DebugThread > {
166
176
return this . getThreads ( thread => thread . stopped ) ;
167
177
}
@@ -238,6 +248,7 @@ export class DebugSession implements CompositeTreeElement {
238
248
await this . initialize ( ) ;
239
249
await this . launchOrAttach ( ) ;
240
250
}
251
+
241
252
protected async initialize ( ) : Promise < void > {
242
253
const response = await this . connection . sendRequest ( 'initialize' , {
243
254
clientID : 'Theia' ,
@@ -251,15 +262,12 @@ export class DebugSession implements CompositeTreeElement {
251
262
supportsVariablePaging : false ,
252
263
supportsRunInTerminalRequest : true
253
264
} ) ;
254
- this . updateCapabilities ( response . body || { } ) ;
265
+ this . updateCapabilities ( response ? .body || { } ) ;
255
266
}
267
+
256
268
protected async launchOrAttach ( ) : Promise < void > {
257
269
try {
258
- if ( this . configuration . request === 'attach' ) {
259
- await this . sendRequest ( 'attach' , this . configuration ) ;
260
- } else {
261
- await this . sendRequest ( 'launch' , this . configuration ) ;
262
- }
270
+ await this . sendRequest ( ( this . configuration . request as keyof DebugRequestTypes ) , this . configuration ) ;
263
271
} catch ( reason ) {
264
272
this . fireExited ( reason ) ;
265
273
await this . messages . showMessage ( {
@@ -272,6 +280,7 @@ export class DebugSession implements CompositeTreeElement {
272
280
throw reason ;
273
281
}
274
282
}
283
+
275
284
protected initialized = false ;
276
285
protected async configure ( ) : Promise < void > {
277
286
if ( this . capabilities . exceptionBreakpointFilters ) {
@@ -302,22 +311,27 @@ export class DebugSession implements CompositeTreeElement {
302
311
await this . disconnect ( restart ) ;
303
312
}
304
313
}
314
+
305
315
protected async disconnect ( restart ?: boolean ) : Promise < void > {
306
- try {
307
- await this . sendRequest ( 'disconnect' , { restart } ) ;
308
- } catch ( reason ) {
309
- this . fireExited ( reason ) ;
310
- return ;
311
- }
312
- const timeout = 500 ;
313
- if ( ! await this . exited ( timeout ) ) {
314
- this . fireExited ( new Error ( `timeout after ${ timeout } ms` ) ) ;
315
- }
316
+ const TIMEOUT_MS = 1000 ;
317
+ Promise . race ( [
318
+ this . sendRequest ( 'disconnect' , { restart } ) ,
319
+ new Promise ( reject => setTimeout ( reject , TIMEOUT_MS , new Error ( 'TIMEOUT_ERR' ) ) )
320
+ ] ) . then ( res => {
321
+ if ( res instanceof Error ) {
322
+ this . fireExited ( res ) ;
323
+ }
324
+ } ) . catch ( this . fireExited ) ;
316
325
}
317
326
318
327
protected fireExited ( reason ?: Error ) : void {
319
- this . connection [ 'fire' ] ( 'exited' , { reason } ) ;
328
+ try {
329
+ this . connection [ 'fire' ] ( 'exited' , { reason } ) ;
330
+ } catch ( e ) {
331
+ console . error ( e ) ;
332
+ }
320
333
}
334
+
321
335
protected exited ( timeout : number ) : Promise < boolean > {
322
336
return new Promise < boolean > ( resolve => {
323
337
const listener = this . on ( 'exited' , ( ) => {
@@ -398,6 +412,7 @@ export class DebugSession implements CompositeTreeElement {
398
412
}
399
413
this . updateCurrentThread ( ) ;
400
414
}
415
+
401
416
protected clearThread ( threadId : number ) : void {
402
417
const thread = this . _threads . get ( threadId ) ;
403
418
if ( thread ) {
@@ -408,6 +423,7 @@ export class DebugSession implements CompositeTreeElement {
408
423
409
424
protected readonly scheduleUpdateThreads = debounce ( ( ) => this . updateThreads ( undefined ) , 100 ) ;
410
425
protected pendingThreads = Promise . resolve ( ) ;
426
+
411
427
updateThreads ( stoppedDetails : StoppedDetails | undefined ) : Promise < void > {
412
428
return this . pendingThreads = this . pendingThreads . then ( async ( ) => {
413
429
try {
@@ -420,6 +436,7 @@ export class DebugSession implements CompositeTreeElement {
420
436
}
421
437
} ) ;
422
438
}
439
+
423
440
protected doUpdateThreads ( threads : DebugProtocol . Thread [ ] , stoppedDetails ?: StoppedDetails ) : void {
424
441
const existing = this . _threads ;
425
442
this . _threads = new Map ( ) ;
@@ -515,7 +532,9 @@ export class DebugSession implements CompositeTreeElement {
515
532
this . fireDidChangeBreakpoints ( new URI ( uri ) ) ;
516
533
}
517
534
}
535
+
518
536
protected updatingBreakpoints = false ;
537
+
519
538
protected updateBreakpoint ( body : DebugProtocol . BreakpointEvent [ 'body' ] ) : void {
520
539
this . updatingBreakpoints = true ;
521
540
try {
@@ -687,6 +706,7 @@ export class DebugSession implements CompositeTreeElement {
687
706
const distinct = this . dedupSourceBreakpoints ( breakpoints ) ;
688
707
this . setBreakpoints ( uri , distinct ) ;
689
708
}
709
+
690
710
protected dedupSourceBreakpoints ( all : DebugSourceBreakpoint [ ] ) : DebugSourceBreakpoint [ ] {
691
711
const positions = new Map < string , DebugSourceBreakpoint > ( ) ;
692
712
for ( const breakpoint of all ) {
@@ -702,6 +722,7 @@ export class DebugSession implements CompositeTreeElement {
702
722
}
703
723
return [ ...positions . values ( ) ] ;
704
724
}
725
+
705
726
protected * getAffectedUris ( uri ?: URI ) : IterableIterator < URI > {
706
727
if ( uri ) {
707
728
yield uri ;
@@ -764,4 +785,10 @@ export class DebugSession implements CompositeTreeElement {
764
785
this . clearThread ( threadId ) ;
765
786
}
766
787
} ;
788
+
789
+ protected registerDebugContributions ( configType : string , connection : DebugSessionConnection ) : void {
790
+ for ( const contrib of this . debugContributionProvider . getContributions ( ) ) {
791
+ contrib . register ( configType , connection ) ;
792
+ }
793
+ } ;
767
794
}
0 commit comments