3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
- import * as path from 'vs/base/common/path' ;
7
- import * as nls from 'vs/nls' ;
8
- import * as Objects from 'vs/base/common/objects' ;
9
- import * as Types from 'vs/base/common/types' ;
10
- import * as Platform from 'vs/base/common/platform' ;
11
6
import * as Async from 'vs/base/common/async' ;
12
- import * as resources from 'vs/base/common/resources' ;
13
7
import { IStringDictionary } from 'vs/base/common/collections' ;
8
+ import { Emitter , Event } from 'vs/base/common/event' ;
9
+ import { isUNC } from 'vs/base/common/extpath' ;
10
+ import { Disposable , DisposableStore } from 'vs/base/common/lifecycle' ;
14
11
import { LinkedMap , Touch } from 'vs/base/common/map' ;
12
+ import * as Objects from 'vs/base/common/objects' ;
13
+ import * as path from 'vs/base/common/path' ;
14
+ import * as Platform from 'vs/base/common/platform' ;
15
+ import * as resources from 'vs/base/common/resources' ;
15
16
import Severity from 'vs/base/common/severity' ;
16
- import { Event , Emitter } from 'vs/base/common/event' ;
17
- import { Disposable , DisposableStore } from 'vs/base/common/lifecycle' ;
18
- import { isUNC } from 'vs/base/common/extpath' ;
17
+ import * as Types from 'vs/base/common/types' ;
18
+ import * as nls from 'vs/nls' ;
19
19
20
+ import { IModelService } from 'vs/editor/common/services/model' ;
20
21
import { IFileService } from 'vs/platform/files/common/files' ;
21
22
import { IMarkerService , MarkerSeverity } from 'vs/platform/markers/common/markers' ;
22
- import { IWorkspaceContextService , WorkbenchState , IWorkspaceFolder } from 'vs/platform/workspace/common/workspace' ;
23
- import { IModelService } from 'vs/editor/common/services/model' ;
24
- import { ProblemMatcher , ProblemMatcherRegistry /*, ProblemPattern, getResource */ } from 'vs/workbench/contrib/tasks/common/problemMatcher' ;
23
+ import { IWorkspaceContextService , IWorkspaceFolder , WorkbenchState } from 'vs/platform/workspace/common/workspace' ;
25
24
import { Markers } from 'vs/workbench/contrib/markers/common/markers' ;
25
+ import { ProblemMatcher , ProblemMatcherRegistry /*, ProblemPattern, getResource */ } from 'vs/workbench/contrib/tasks/common/problemMatcher' ;
26
26
27
- import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver' ;
28
- import { ITerminalProfileResolverService , TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal' ;
29
- import { ITerminalService , ITerminalInstance , ITerminalGroupService } from 'vs/workbench/contrib/terminal/browser/terminal' ;
30
- import { IOutputService } from 'vs/workbench/services/output/common/output' ;
31
- import { StartStopProblemCollector , WatchingProblemCollector , ProblemCollectorEventKind , ProblemHandlingStrategy } from 'vs/workbench/contrib/tasks/common/problemCollectors' ;
32
- import {
33
- Task , CustomTask , ContributedTask , RevealKind , CommandOptions , IShellConfiguration , RuntimeType , PanelKind ,
34
- TaskEvent , TaskEventKind , IShellQuotingOptions , ShellQuoting , CommandString , ICommandConfiguration , IExtensionTaskSource , TaskScope , RevealProblemKind , DependsOrder , TaskSourceKind , InMemoryTask , ITaskEvent , TaskSettingId
35
- } from 'vs/workbench/contrib/tasks/common/tasks' ;
36
- import {
37
- ITaskSystem , ITaskSummary , ITaskExecuteResult , TaskExecuteKind , TaskError , TaskErrors , ITaskResolver ,
38
- Triggers , ITaskTerminateResponse , ITaskSystemInfoResolver , ITaskSystemInfo , IResolveSet , IResolvedVariables
39
- } from 'vs/workbench/contrib/tasks/common/taskSystem' ;
40
- import { URI } from 'vs/base/common/uri' ;
41
- import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService' ;
27
+ import { Codicon } from 'vs/base/common/codicons' ;
42
28
import { Schemas } from 'vs/base/common/network' ;
43
- import { IPathService } from 'vs/workbench/services/path/common/pathService' ;
44
- import { IViewsService , IViewDescriptorService , ViewContainerLocation } from 'vs/workbench/common/views' ;
45
- import { ILogService } from 'vs/platform/log/common/log' ;
29
+ import { URI } from 'vs/base/common/uri' ;
46
30
import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
47
- import { IShellLaunchConfig , TerminalLocation , TerminalSettingId } from 'vs/platform/terminal/common/terminal' ;
48
- import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy' ;
49
- import { TaskTerminalStatus } from 'vs/workbench/contrib/tasks/browser/taskTerminalStatus' ;
50
- import { ITaskService } from 'vs/workbench/contrib/tasks/common/taskService' ;
51
- import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite' ;
31
+ import { ILogService } from 'vs/platform/log/common/log' ;
52
32
import { INotificationService } from 'vs/platform/notification/common/notification' ;
53
- import { ThemeIcon } from 'vs/platform/theme /common/themeService ' ;
33
+ import { IShellLaunchConfig , TerminalLocation , TerminalSettingId } from 'vs/platform/terminal /common/terminal ' ;
54
34
import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings' ;
35
+ import { ThemeIcon } from 'vs/platform/theme/common/themeService' ;
36
+ import { IViewDescriptorService , IViewsService , ViewContainerLocation } from 'vs/workbench/common/views' ;
37
+ import { TaskTerminalStatus } from 'vs/workbench/contrib/tasks/browser/taskTerminalStatus' ;
38
+ import { ProblemCollectorEventKind , ProblemHandlingStrategy , StartStopProblemCollector , WatchingProblemCollector } from 'vs/workbench/contrib/tasks/common/problemCollectors' ;
55
39
import { GroupKind } from 'vs/workbench/contrib/tasks/common/taskConfiguration' ;
56
- import { Codicon } from 'vs/base/common/codicons' ;
40
+ import { CommandOptions , CommandString , ContributedTask , CustomTask , DependsOrder , ICommandConfiguration , IExtensionTaskSource , InMemoryTask , IShellConfiguration , IShellQuotingOptions , ITaskEvent , PanelKind , RevealKind , RevealProblemKind , RuntimeType , ShellQuoting , Task , TaskEvent , TaskEventKind , TaskScope , TaskSettingId , TaskSourceKind } from 'vs/workbench/contrib/tasks/common/tasks' ;
41
+ import { ITaskService } from 'vs/workbench/contrib/tasks/common/taskService' ;
42
+ import { IResolvedVariables , IResolveSet , ITaskExecuteResult , ITaskResolver , ITaskSummary , ITaskSystem , ITaskSystemInfo , ITaskSystemInfoResolver , ITaskTerminateResponse , TaskError , TaskErrors , TaskExecuteKind , Triggers } from 'vs/workbench/contrib/tasks/common/taskSystem' ;
43
+ import { ITerminalGroupService , ITerminalInstance , ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal' ;
57
44
import { VSCodeOscProperty , VSCodeOscPt , VSCodeSequence } from 'vs/workbench/contrib/terminal/browser/terminalEscapeSequences' ;
45
+ import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy' ;
46
+ import { ITerminalProfileResolverService , TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal' ;
47
+ import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver' ;
48
+ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService' ;
49
+ import { IOutputService } from 'vs/workbench/services/output/common/output' ;
50
+ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite' ;
51
+ import { IPathService } from 'vs/workbench/services/path/common/pathService' ;
58
52
59
53
interface ITerminalData {
60
54
terminal : ITerminalInstance ;
@@ -205,7 +199,8 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
205
199
private _previousTerminalInstance : ITerminalInstance | undefined ;
206
200
private _terminalStatusManager : TaskTerminalStatus ;
207
201
private _terminalCreationQueue : Promise < ITerminalInstance | void > = Promise . resolve ( ) ;
208
-
202
+ private _hasReconnected : boolean = false ;
203
+ private _tasksToReconnect : string [ ] = [ ] ;
209
204
private readonly _onDidStateChange : Emitter < ITaskEvent > ;
210
205
211
206
get taskShellIntegrationStartSequence ( ) : string {
@@ -245,12 +240,23 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
245
240
this . _terminals = Object . create ( null ) ;
246
241
this . _idleTaskTerminals = new LinkedMap < string , string > ( ) ;
247
242
this . _sameTaskTerminals = Object . create ( null ) ;
248
-
249
243
this . _onDidStateChange = new Emitter ( ) ;
250
244
this . _taskSystemInfoResolver = taskSystemInfoResolver ;
251
245
this . _register ( this . _terminalStatusManager = new TaskTerminalStatus ( taskService ) ) ;
252
246
}
253
247
248
+ private _reconnectToTerminals ( terminals : ITerminalInstance [ ] ) : void {
249
+ for ( const terminal of terminals ) {
250
+ const taskForTerminal = terminal . shellLaunchConfig . attachPersistentProcess ?. task ;
251
+ if ( taskForTerminal ?. id && taskForTerminal ?. lastTask ) {
252
+ this . _tasksToReconnect . push ( taskForTerminal . id ) ;
253
+ this . _terminals [ terminal . instanceId ] = { terminal, lastTask : taskForTerminal . lastTask , group : taskForTerminal . group } ;
254
+ } else {
255
+ this . _logService . trace ( `Could not reconnect to terminal ${ terminal . instanceId } with process details ${ terminal . shellLaunchConfig . attachPersistentProcess } ` ) ;
256
+ }
257
+ }
258
+ }
259
+
254
260
public get onDidStateChange ( ) : Event < ITaskEvent > {
255
261
return this . _onDidStateChange . event ;
256
262
}
@@ -263,6 +269,19 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
263
269
this . _outputService . showChannel ( this . _outputChannelId , true ) ;
264
270
}
265
271
272
+ public reconnect ( task : Task , resolver : ITaskResolver , trigger : string = Triggers . command ) : ITaskExecuteResult | undefined {
273
+ const terminals = this . _terminalService . getReconnectedTerminals ( 'Task' ) ;
274
+ if ( ! this . _hasReconnected && terminals && terminals . length > 0 ) {
275
+ this . _reconnectToTerminals ( terminals ) ;
276
+ this . _hasReconnected = true ;
277
+ }
278
+ if ( this . _tasksToReconnect . includes ( task . _id ) ) {
279
+ this . _lastTask = new VerifiedTask ( task , resolver , trigger ) ;
280
+ this . rerun ( ) ;
281
+ }
282
+ return undefined ;
283
+ }
284
+
266
285
public run ( task : Task , resolver : ITaskResolver , trigger : string = Triggers . command ) : ITaskExecuteResult {
267
286
task = task . clone ( ) ; // A small amount of task state is stored in the task (instance) and tasks passed in to run may have that set already.
268
287
const recentTaskKey = task . getRecentlyUsedKey ( ) ?? '' ;
@@ -1269,7 +1288,18 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
1269
1288
return createdTerminal ;
1270
1289
}
1271
1290
1291
+ private _reviveTerminals ( ) : void {
1292
+ if ( Object . entries ( this . _terminals ) . length === 0 ) {
1293
+ for ( const terminal of this . _terminalService . instances ) {
1294
+ if ( terminal . shellLaunchConfig . attachPersistentProcess ?. task ?. lastTask ) {
1295
+ this . _terminals [ terminal . instanceId ] = { lastTask : terminal . shellLaunchConfig . attachPersistentProcess . task . lastTask , group : terminal . shellLaunchConfig . attachPersistentProcess . task . group , terminal } ;
1296
+ }
1297
+ }
1298
+ }
1299
+ }
1300
+
1272
1301
private async _createTerminal ( task : CustomTask | ContributedTask , resolver : VariableResolver , workspaceFolder : IWorkspaceFolder | undefined ) : Promise < [ ITerminalInstance | undefined , TaskError | undefined ] > {
1302
+ this . _reviveTerminals ( ) ;
1273
1303
const platform = resolver . taskSystemInfo ? resolver . taskSystemInfo . platform : Platform . platform ;
1274
1304
const options = await this . _resolveOptions ( resolver , task . command . options ) ;
1275
1305
const presentationOptions = task . command . presentation ;
@@ -1308,7 +1338,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
1308
1338
} , 'Executing task: {0}' , task . _label ) , { excludeLeadingNewLine : true } ) : undefined ,
1309
1339
isFeatureTerminal : true ,
1310
1340
icon : task . configurationProperties . icon ?. id ? ThemeIcon . fromId ( task . configurationProperties . icon . id ) : undefined ,
1311
- color : task . configurationProperties . icon ?. color || undefined ,
1341
+ color : task . configurationProperties . icon ?. color || undefined
1312
1342
} ;
1313
1343
} else {
1314
1344
const resolvedResult : { command : CommandString ; args : CommandString [ ] } = await this . _resolveCommandAndArgs ( resolver , task . command ) ;
@@ -1369,9 +1399,10 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {
1369
1399
1370
1400
this . _terminalCreationQueue = this . _terminalCreationQueue . then ( ( ) => this . _doCreateTerminal ( group , launchConfigs ! ) ) ;
1371
1401
const result : ITerminalInstance = ( await this . _terminalCreationQueue ) ! ;
1372
-
1402
+ result . shellLaunchConfig . task = { lastTask : taskKey , group, label : task . _label , id : task . _id } ;
1403
+ result . shellLaunchConfig . reconnectionOwner = 'Task' ;
1373
1404
const terminalKey = result . instanceId . toString ( ) ;
1374
- result . onDisposed ( ( terminal ) => {
1405
+ result . onDisposed ( ( ) => {
1375
1406
const terminalData = this . _terminals [ terminalKey ] ;
1376
1407
if ( terminalData ) {
1377
1408
delete this . _terminals [ terminalKey ] ;
0 commit comments