private doExecuteTask()

in src/vs/workbench/contrib/tasks/node/processTaskSystem.ts [205:358]


	private doExecuteTask(task: CustomTask, telemetryEvent: TelemetryEvent): ITaskExecuteResult {
		let taskSummary: ITaskSummary = {};
		let commandConfig: CommandConfiguration = task.command;
		if (!this.errorsShown) {
			this.showOutput();
			this.errorsShown = true;
		} else {
			this.clearOutput();
		}

		let args: string[] = [];
		if (commandConfig.args) {
			for (let arg of commandConfig.args) {
				if (Types.isString(arg)) {
					args.push(arg);
				} else {
					this.log(`Quoting individual arguments is not supported in the process runner. Using plain value: ${arg.value}`);
					args.push(arg.value);
				}
			}
		}
		args = this.resolveVariables(task, args);
		let command: string = this.resolveVariable(task, Types.isString(commandConfig.name) ? commandConfig.name : commandConfig.name!.value);
		this.childProcess = new LineProcess(command, args, commandConfig.runtime === RuntimeType.Shell, this.resolveOptions(task, commandConfig.options!));
		telemetryEvent.command = this.childProcess.getSanitizedCommand();
		// we have no problem matchers defined. So show the output log
		let reveal = task.command.presentation!.reveal;
		if (reveal === RevealKind.Always || (reveal === RevealKind.Silent && task.configurationProperties.problemMatchers!.length === 0)) {
			this.showOutput();
		}

		if (commandConfig.presentation!.echo) {
			let prompt: string = Platform.isWindows ? '>' : '$';
			this.log(`running command${prompt} ${command} ${args.join(' ')}`);
		}
		if (task.configurationProperties.isBackground) {
			let watchingProblemMatcher = new WatchingProblemCollector(this.resolveMatchers(task, task.configurationProperties.problemMatchers!), this.markerService, this.modelService);
			let toDispose: IDisposable[] | null = [];
			let eventCounter: number = 0;
			toDispose.push(watchingProblemMatcher.onDidStateChange((event) => {
				if (event.kind === ProblemCollectorEventKind.BackgroundProcessingBegins) {
					eventCounter++;
					this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task));
				} else if (event.kind === ProblemCollectorEventKind.BackgroundProcessingEnds) {
					eventCounter--;
					this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Inactive, task));
				}
			}));
			watchingProblemMatcher.aboutToStart();
			let delayer: Async.Delayer<any> | null = null;
			this.activeTask = task;
			const inactiveEvent = TaskEvent.create(TaskEventKind.Inactive, task);
			let processStartedSignaled: boolean = false;
			const onProgress = (progress: LineData) => {
				let line = Strings.removeAnsiEscapeCodes(progress.line);
				this.appendOutput(line + '\n');
				watchingProblemMatcher.processLine(line);
				if (delayer === null) {
					delayer = new Async.Delayer(3000);
				}
				delayer.trigger(() => {
					watchingProblemMatcher.forceDelivery();
					return null;
				}).then(() => {
					delayer = null;
				});
			};
			const startPromise = this.childProcess.start(onProgress);
			this.childProcess.pid.then(pid => {
				if (pid !== -1) {
					processStartedSignaled = true;
					this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.ProcessStarted, task, pid));
				}
			});
			this.activeTaskPromise = startPromise.then((success): ITaskSummary => {
				this.childProcessEnded();
				watchingProblemMatcher.done();
				watchingProblemMatcher.dispose();
				if (processStartedSignaled && task.command.runtime !== RuntimeType.CustomExecution) {
					this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.ProcessEnded, task, success.cmdCode!));
				}
				toDispose = dispose(toDispose!);
				toDispose = null;
				for (let i = 0; i < eventCounter; i++) {
					this._onDidStateChange.fire(inactiveEvent);
				}
				eventCounter = 0;
				if (!this.checkTerminated(task, success)) {
					this.log(nls.localize('TaskRunnerSystem.watchingBuildTaskFinished', '\nWatching build tasks has finished.'));
				}
				if (success.cmdCode && success.cmdCode === 1 && watchingProblemMatcher.numberOfMatches === 0 && reveal !== RevealKind.Never) {
					this.showOutput();
				}
				taskSummary.exitCode = success.cmdCode;
				return taskSummary;
			}, (error: ErrorData) => {
				this.childProcessEnded();
				watchingProblemMatcher.dispose();
				toDispose = dispose(toDispose!);
				toDispose = null;
				for (let i = 0; i < eventCounter; i++) {
					this._onDidStateChange.fire(inactiveEvent);
				}
				eventCounter = 0;
				return this.handleError(task, error);
			});
			let result: ITaskExecuteResult = (<any>task).tscWatch
				? { kind: TaskExecuteKind.Started, task, started: { restartOnFileChanges: '**/*.ts' }, promise: this.activeTaskPromise }
				: { kind: TaskExecuteKind.Started, task, started: {}, promise: this.activeTaskPromise };
			return result;
		} else {
			this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Start, task));
			this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Active, task));
			let startStopProblemMatcher = new StartStopProblemCollector(this.resolveMatchers(task, task.configurationProperties.problemMatchers!), this.markerService, this.modelService);
			this.activeTask = task;
			const inactiveEvent = TaskEvent.create(TaskEventKind.Inactive, task);
			let processStartedSignaled: boolean = false;
			const onProgress = (progress: LineData) => {
				let line = Strings.removeAnsiEscapeCodes(progress.line);
				this.appendOutput(line + '\n');
				startStopProblemMatcher.processLine(line);
			};
			const startPromise = this.childProcess.start(onProgress);
			this.childProcess.pid.then(pid => {
				if (pid !== -1) {
					processStartedSignaled = true;
					this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.ProcessStarted, task, pid));
				}
			});
			this.activeTaskPromise = startPromise.then((success): ITaskSummary => {
				this.childProcessEnded();
				startStopProblemMatcher.done();
				startStopProblemMatcher.dispose();
				this.checkTerminated(task, success);
				if (processStartedSignaled && task.command.runtime !== RuntimeType.CustomExecution) {
					this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.ProcessEnded, task, success.cmdCode!));
				}
				this._onDidStateChange.fire(inactiveEvent);
				this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task));
				if (success.cmdCode && success.cmdCode === 1 && startStopProblemMatcher.numberOfMatches === 0 && reveal !== RevealKind.Never) {
					this.showOutput();
				}
				taskSummary.exitCode = success.cmdCode;
				return taskSummary;
			}, (error: ErrorData) => {
				this.childProcessEnded();
				startStopProblemMatcher.dispose();
				this._onDidStateChange.fire(inactiveEvent);
				this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.End, task));
				return this.handleError(task, error);
			});
			return { kind: TaskExecuteKind.Started, task, started: {}, promise: this.activeTaskPromise };
		}
	}