Merge from vscode 718331d6f3ebd1b571530ab499edb266ddd493d5

This commit is contained in:
ADS Merger
2020-02-08 04:50:58 +00:00
parent 8c61538a27
commit 2af13c18d2
752 changed files with 16458 additions and 10063 deletions

View File

@@ -7,6 +7,7 @@ import * as nls from 'vs/nls';
import Severity from 'vs/base/common/severity';
import * as Objects from 'vs/base/common/objects';
import * as resources from 'vs/base/common/resources';
import * as json from 'vs/base/common/json';
import { URI } from 'vs/base/common/uri';
import { IStringDictionary } from 'vs/base/common/collections';
import { Action } from 'vs/base/common/actions';
@@ -26,21 +27,20 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IFileService, IFileStat } from 'vs/platform/files/common/files';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { ProblemMatcherRegistry, NamedProblemMatcher } from 'vs/workbench/contrib/tasks/common/problemMatcher';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IProgressService, IProgressOptions, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { INotificationService, IPromptChoice } from 'vs/platform/notification/common/notification';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IDialogService, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import Constants from 'vs/workbench/contrib/markers/browser/constants';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace';
@@ -63,7 +63,7 @@ import { getTemplates as getTaskTemplates } from 'vs/workbench/contrib/tasks/com
import * as TaskConfig from '../common/taskConfiguration';
import { TerminalTaskSystem } from './terminalTaskSystem';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { IQuickInputService, IQuickPickItem, QuickPickInput, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -75,10 +75,12 @@ import { format } from 'vs/base/common/jsonFormatter';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { applyEdits } from 'vs/base/common/jsonEdit';
import { ITextEditor } from 'vs/workbench/common/editor';
import { ITextEditorSelection } from 'vs/platform/editor/common/editor';
import { ITextEditorSelection, TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { find } from 'vs/base/common/arrays';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IViewsService } from 'vs/workbench/common/views';
import { ProviderProgressMananger } from 'vs/workbench/contrib/tasks/browser/providerProgressManager';
const QUICKOPEN_HISTORY_LIMIT_CONFIG = 'task.quickOpen.history';
const QUICKOPEN_DETAIL_CONFIG = 'task.quickOpen.detail';
@@ -219,6 +221,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
private _providers: Map<number, ITaskProvider>;
private _providerTypes: Map<number, string>;
protected _taskSystemInfos: Map<string, TaskSystemInfo>;
private _providerProgressManager: ProviderProgressMananger | undefined;
protected _workspaceTasksPromise?: Promise<Map<string, WorkspaceFolderTaskResult>>;
protected _areJsonTasksSupportedPromise: Promise<boolean> = Promise.resolve(false);
@@ -237,6 +240,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
@IMarkerService protected readonly markerService: IMarkerService,
@IOutputService protected readonly outputService: IOutputService,
@IPanelService private readonly panelService: IPanelService,
@IViewsService private readonly viewsService: IViewsService,
@ICommandService private readonly commandService: ICommandService,
@IEditorService private readonly editorService: IEditorService,
@IFileService protected readonly fileService: IFileService,
@IWorkspaceContextService protected readonly contextService: IWorkspaceContextService,
@@ -256,7 +261,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
@INotificationService private readonly notificationService: INotificationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@ITerminalInstanceService private readonly terminalInstanceService: ITerminalInstanceService,
@IRemotePathService private readonly remotePathService: IRemotePathService,
@ITextModelService private readonly textModelResolverService: ITextModelService,
@@ -412,19 +416,19 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return this.runShowTasks();
});
CommandsRegistry.registerCommand('workbench.action.tasks.toggleProblems', () => {
const panel = this.panelService.getActivePanel();
if (panel && panel.getId() === Constants.MARKERS_PANEL_ID) {
this.layoutService.setPanelHidden(true);
} else {
this.panelService.openPanel(Constants.MARKERS_PANEL_ID, true);
CommandsRegistry.registerCommand('workbench.action.tasks.toggleProblems', () => this.commandService.executeCommand(Constants.TOGGLE_MARKERS_VIEW_ACTION_ID));
CommandsRegistry.registerCommand('workbench.action.tasks.openUserTasks', async () => {
const resource = this.getResourceForKind(TaskSourceKind.User);
if (resource) {
this.openTaskFile(resource, TaskSourceKind.User);
}
});
CommandsRegistry.registerCommand('workbench.action.tasks.configureUserTask', async () => {
const resource = this.getResourceForKind(TaskSourceKind.User);
CommandsRegistry.registerCommand('workbench.action.tasks.openWorkspaceFileTasks', async () => {
const resource = this.getResourceForKind(TaskSourceKind.WorkspaceFile);
if (resource) {
this.openTaskFile(resource);
this.openTaskFile(resource, TaskSourceKind.WorkspaceFile);
}
});
}
@@ -960,7 +964,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
pinned: false,
forceReload: true, // because content might have changed
selection,
revealInCenterIfOutsideViewport: !!selection
selectionRevealType: TextEditorSelectionRevealType.CenterIfOutsideViewport
}
});
});
@@ -971,7 +975,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (!workspaceFolder) {
return Promise.resolve(undefined);
}
let configuration = this.getConfiguration(workspaceFolder);
let configuration = this.getConfiguration(workspaceFolder, task._source.kind);
if (configuration.hasParseErrors) {
this.notificationService.warn(nls.localize('customizeParseErrors', 'The current task configuration has errors. Please fix the errors first before customizing a task.'));
return Promise.resolve<void>(undefined);
@@ -983,7 +987,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
let taskConfig = CustomTask.is(task) ? task._source.config : undefined;
if (taskConfig && taskConfig.element) {
index = taskConfig.index;
toCustomize = taskConfig.element;
toCustomize = { ...(taskConfig.element) };
} else if (ContributedTask.is(task)) {
toCustomize = {
};
@@ -1033,10 +1037,10 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if ((index === -1) && properties) {
if (properties.problemMatcher !== undefined) {
fileConfig.problemMatcher = properties.problemMatcher;
promise = this.writeConfiguration(workspaceFolder, 'tasks.problemMatchers', fileConfig.problemMatcher);
promise = this.writeConfiguration(workspaceFolder, 'tasks.problemMatchers', fileConfig.problemMatcher, task._source.kind);
} else if (properties.group !== undefined) {
fileConfig.group = properties.group;
promise = this.writeConfiguration(workspaceFolder, 'tasks.group', fileConfig.group);
promise = this.writeConfiguration(workspaceFolder, 'tasks.group', fileConfig.group, task._source.kind);
}
} else {
if (!Array.isArray(fileConfig.tasks)) {
@@ -1047,7 +1051,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
} else {
fileConfig.tasks[index] = toCustomize;
}
promise = this.writeConfiguration(workspaceFolder, 'tasks.tasks', fileConfig.tasks);
promise = this.writeConfiguration(workspaceFolder, 'tasks.tasks', fileConfig.tasks, task._source.kind);
}
}
if (!promise) {
@@ -1064,22 +1068,31 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
*/
this.telemetryService.publicLog(AbstractTaskService.CustomizationTelemetryEventName, event);
if (openConfig) {
this.openEditorAtTask(workspaceFolder.toResource('.vscode/tasks.json'), toCustomize);
this.openEditorAtTask(this.getResourceForTask(task), toCustomize);
}
});
}
private writeConfiguration(workspaceFolder: IWorkspaceFolder, key: string, value: any): Promise<void> | undefined {
if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) {
return this.configurationService.updateValue(key, value, { resource: workspaceFolder.uri }, ConfigurationTarget.WORKSPACE);
} else if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
return this.configurationService.updateValue(key, value, { resource: workspaceFolder.uri }, ConfigurationTarget.WORKSPACE_FOLDER);
private writeConfiguration(workspaceFolder: IWorkspaceFolder, key: string, value: any, source?: string): Promise<void> | undefined {
let target: ConfigurationTarget | undefined = undefined;
switch (source) {
case TaskSourceKind.User: target = ConfigurationTarget.USER; break;
case TaskSourceKind.WorkspaceFile: target = ConfigurationTarget.WORKSPACE; break;
default: if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) {
target = ConfigurationTarget.WORKSPACE;
} else if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
target = ConfigurationTarget.WORKSPACE_FOLDER;
}
}
if (target) {
return this.configurationService.updateValue(key, value, { resource: workspaceFolder.uri }, target);
} else {
return undefined;
}
}
private getResourceForKind(kind: string): URI | undefined {
this.updateSetup();
switch (kind) {
case TaskSourceKind.User: {
return resources.joinPath(resources.dirname(this.preferencesService.userSettingsResource), 'tasks.json');
@@ -1095,17 +1108,21 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
}
private getResourceForTask(task: CustomTask): URI {
let uri = this.getResourceForKind(task._source.kind);
if (!uri) {
const taskFolder = task.getWorkspaceFolder();
if (taskFolder) {
uri = taskFolder.toResource(task._source.config.file);
} else {
uri = this.workspaceFolders[0].uri;
private getResourceForTask(task: CustomTask | ContributedTask): URI {
if (CustomTask.is(task)) {
let uri = this.getResourceForKind(task._source.kind);
if (!uri) {
const taskFolder = task.getWorkspaceFolder();
if (taskFolder) {
uri = taskFolder.toResource(task._source.config.file);
} else {
uri = this.workspaceFolders[0].uri;
}
}
return uri;
} else {
return task.getWorkspaceFolder()!.toResource('.vscode/tasks.json');
}
return uri;
}
public openConfig(task: CustomTask | undefined): Promise<void> {
@@ -1262,14 +1279,15 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (active && active.same) {
if (this._taskSystem?.isTaskVisible(executeResult.task)) {
const message = nls.localize('TaskSystem.activeSame.noBackground', 'The task \'{0}\' is already active.', executeResult.task.getQualifiedLabel());
let lastInstance = this.getTaskSystem().getLastInstance(executeResult.task) ?? executeResult.task;
this.notificationService.prompt(Severity.Info, message,
[{
label: nls.localize('terminateTask', "Terminate Task"),
run: () => this.terminate(executeResult.task)
run: () => this.terminate(lastInstance)
},
{
label: nls.localize('restartTask', "Restart Task"),
run: () => this.restart(executeResult.task)
run: () => this.restart(lastInstance)
}],
{ sticky: true }
);
@@ -1315,7 +1333,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
protected createTerminalTaskSystem(): ITaskSystem {
return new TerminalTaskSystem(
this.terminalService, this.outputService, this.panelService, this.markerService,
this.terminalService, this.outputService, this.panelService, this.viewsService, this.markerService,
this.modelService, this.configurationResolverService, this.telemetryService,
this.contextService, this.environmentService,
AbstractTaskService.OutputChannelId, this.fileService, this.terminalInstanceService,
@@ -1331,36 +1349,26 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
protected abstract getTaskSystem(): ITaskSystem;
private async provideTasksWithWarning(provider: ITaskProvider, type: string, validTypes: IStringDictionary<boolean>): Promise<TaskSet> {
private async provideTasksWithWarning(provider: ITaskProvider, type: string, validTypes: IStringDictionary<boolean>): Promise<TaskSet | undefined> {
return new Promise<TaskSet>(async (resolve, reject) => {
let isDone = false;
provider.provideTasks(validTypes).then((value) => {
let disposable: IDisposable | undefined;
const providePromise = provider.provideTasks(validTypes);
this._providerProgressManager?.addProvider(type, providePromise);
disposable = this._providerProgressManager?.canceled.token.onCancellationRequested(() => {
if (!isDone) {
resolve();
}
});
providePromise.then((value) => {
isDone = true;
disposable?.dispose();
resolve(value);
}, (e) => {
isDone = true;
disposable?.dispose();
reject(e);
});
let settingValue: boolean | string[] = this.configurationService.getValue('task.slowProviderWarning');
if ((settingValue === true) || (Types.isStringArray(settingValue) && (settingValue.indexOf(type) < 0))) {
setTimeout(() => {
if (!isDone) {
const settings: IPromptChoice = { label: nls.localize('TaskSystem.slowProvider.settings', "Settings"), run: () => this.preferencesService.openSettings(false, undefined) };
const disableAll: IPromptChoice = { label: nls.localize('TaskSystem.slowProvider.disableAll', "Disable All"), run: () => this.configurationService.updateValue('task.autoDetect', 'off') };
const dontShow: IPromptChoice = {
label: nls.localize('TaskSystem.slowProvider.dontShow', "Don't warn again for {0} tasks", type), run: () => {
if (!Types.isStringArray(settingValue)) {
settingValue = [];
}
settingValue.push(type);
return this.configurationService.updateValue('task.slowProviderWarning', settingValue);
}
};
this.notificationService.prompt(Severity.Warning, nls.localize('TaskSystem.slowProvider', "The {0} task provider is slow. The extension that provides {0} tasks may provide a setting to disable it, or you can disable all tasks providers", type),
[settings, disableAll, dontShow]);
}
}, 4000);
}
});
}
@@ -1370,10 +1378,11 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
TaskDefinitionRegistry.all().forEach(definition => validTypes[definition.taskType] = true);
validTypes['shell'] = true;
validTypes['process'] = true;
this._providerProgressManager = new ProviderProgressMananger();
return new Promise<TaskSet[]>(resolve => {
let result: TaskSet[] = [];
let counter: number = 0;
let done = (value: TaskSet) => {
let done = (value: TaskSet | undefined) => {
if (value) {
result.push(value);
}
@@ -1790,10 +1799,19 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return TaskConfig.JsonSchemaVersion.from(config);
}
protected getConfiguration(workspaceFolder: IWorkspaceFolder): { config: TaskConfig.ExternalTaskRunnerConfiguration | undefined; hasParseErrors: boolean } {
let result = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY
? Objects.deepClone(this.configurationService.inspect<TaskConfig.ExternalTaskRunnerConfiguration>('tasks', { resource: workspaceFolder.uri }).workspaceFolderValue)
: undefined;
protected getConfiguration(workspaceFolder: IWorkspaceFolder, source?: string): { config: TaskConfig.ExternalTaskRunnerConfiguration | undefined; hasParseErrors: boolean } {
let result;
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
result = undefined;
} else {
const wholeConfig = this.configurationService.inspect<TaskConfig.ExternalTaskRunnerConfiguration>('tasks', { resource: workspaceFolder.uri });
switch (source) {
case TaskSourceKind.User: result = Objects.deepClone(wholeConfig.userValue); break;
case TaskSourceKind.Workspace: result = Objects.deepClone(wholeConfig.workspaceFolderValue); break;
case TaskSourceKind.WorkspaceFile: result = Objects.deepClone(wholeConfig.workspaceValue); break;
default: result = Objects.deepClone(wholeConfig.workspaceFolderValue);
}
}
if (!result) {
return { config: undefined, hasParseErrors: false };
}
@@ -1943,23 +1961,21 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
private createTaskQuickPickEntries(tasks: Task[], group: boolean = false, sort: boolean = false, selectedEntry?: TaskQuickPickEntry): TaskQuickPickEntry[] {
let count: { [key: string]: number; } = {};
if (tasks === undefined || tasks === null || tasks.length === 0) {
return [];
}
const TaskQuickPickEntry = (task: Task): TaskQuickPickEntry => {
let description: string | undefined;
if (task._source.kind === TaskSourceKind.User) {
description = nls.localize('taskQuickPick.userSettings', 'User Settings');
} else if (task._source.kind === TaskSourceKind.WorkspaceFile) {
description = task.getWorkspaceFileName();
} else if (this.needsFolderQualification()) {
let workspaceFolder = task.getWorkspaceFolder();
if (workspaceFolder) {
description = workspaceFolder.name;
}
let entryLabel = task._label;
let commonKey = task._id.split('|')[0];
if (count[commonKey]) {
entryLabel = entryLabel + ' (' + count[commonKey].toString() + ')';
count[commonKey]++;
} else {
count[commonKey] = 1;
}
return { label: entryLabel, description: this.getTaskDescription(task), task, detail: this.showDetail() ? task.configurationProperties.detail : undefined };
return { label: task._label, description, task, detail: this.showDetail() ? task.configurationProperties.detail : undefined };
};
function fillEntries(entries: QuickPickInput<TaskQuickPickEntry>[], tasks: Task[], groupLabel: string): void {
if (tasks.length) {
@@ -2022,6 +2038,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
entries = tasks.map<TaskQuickPickEntry>(task => TaskQuickPickEntry(task));
}
count = {};
return entries;
}
@@ -2061,30 +2078,69 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
}
return entries;
});
return this.quickInputService.pick(pickEntries, {
placeHolder,
matchOnDescription: true,
onDidTriggerItemButton: context => {
let task = context.item.task;
this.quickInputService.cancel();
if (ContributedTask.is(task)) {
this.customize(task, undefined, true);
} else if (CustomTask.is(task)) {
this.openConfig(task);
const picker: IQuickPick<TaskQuickPickEntry> = this.quickInputService.createQuickPick();
picker.placeholder = placeHolder;
picker.matchOnDescription = true;
picker.ignoreFocusOut = true;
picker.onDidTriggerItemButton(context => {
let task = context.item.task;
this.quickInputService.cancel();
if (ContributedTask.is(task)) {
this.customize(task, undefined, true);
} else if (CustomTask.is(task)) {
this.openConfig(task);
}
});
picker.busy = true;
const progressManager = this._providerProgressManager;
const progressTimeout = setTimeout(() => {
if (progressManager) {
progressManager.showProgress = (stillProviding) => {
let message = undefined;
if (stillProviding.length > 0) {
message = nls.localize('pickProgressManager.description', 'Getting tasks from extensions. {0} extension(s) remaining: {1}', stillProviding.length, stillProviding.join(', '));
}
picker.description = message;
};
progressManager.addOnDoneListener(() => {
picker.focusOnInput();
picker.customButton = false;
});
if (!progressManager.isDone) {
picker.customLabel = nls.localize('taskQuickPick.cancel', "Cancel Remaining Extensions");
picker.onDidCustom(() => {
this._providerProgressManager?.cancel();
});
picker.customButton = true;
}
}
}, cancellationToken).then(async (selection) => {
if (cancellationToken.isCancellationRequested) {
// canceled when there's only one task
const task = (await pickEntries)[0];
if ((<any>task).task) {
selection = <TaskQuickPickEntry>task;
}, 1000);
pickEntries.then(entries => {
clearTimeout(progressTimeout);
progressManager?.dispose();
picker.busy = false;
picker.items = entries;
});
picker.show();
return new Promise<TaskQuickPickEntry | undefined | null>(resolve => {
this._register(picker.onDidAccept(async () => {
let selection = picker.selectedItems ? picker.selectedItems[0] : undefined;
if (cancellationToken.isCancellationRequested) {
// canceled when there's only one task
const task = (await pickEntries)[0];
if ((<any>task).task) {
selection = <TaskQuickPickEntry>task;
}
}
}
if (!selection) {
return undefined; //{{SQL CARBON EDIT}} strict-null-check
}
return selection;
picker.dispose();
if (!selection) {
resolve();
}
resolve(selection);
}));
});
}
@@ -2421,17 +2477,25 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return result;
}
private openTaskFile(resource: URI) {
private openTaskFile(resource: URI, taskSource: string) {
let configFileCreated = false;
this.fileService.resolve(resource).then((stat) => stat, () => undefined).then((stat) => {
if (stat) {
return stat.resource;
this.fileService.resolve(resource).then((stat) => stat, () => undefined).then(async (stat) => {
const fileExists: boolean = !!stat;
const configValue = this.configurationService.inspect<TaskConfig.ExternalTaskRunnerConfiguration>('tasks');
let tasksExistInFile: boolean;
let target: ConfigurationTarget;
switch (taskSource) {
case TaskSourceKind.User: tasksExistInFile = !!configValue.userValue; target = ConfigurationTarget.USER; break;
case TaskSourceKind.WorkspaceFile: tasksExistInFile = !!configValue.workspaceValue; target = ConfigurationTarget.WORKSPACE; break;
default: tasksExistInFile = !!configValue.value; target = ConfigurationTarget.WORKSPACE_FOLDER;
}
return this.quickInputService.pick(getTaskTemplates(), { placeHolder: nls.localize('TaskService.template', 'Select a Task Template') }).then((selection) => {
if (!selection) {
let content;
if (!tasksExistInFile) {
const pickTemplateResult = await this.quickInputService.pick(getTaskTemplates(), { placeHolder: nls.localize('TaskService.template', 'Select a Task Template') });
if (!pickTemplateResult) {
return Promise.resolve(undefined);
}
let content = selection.content;
content = pickTemplateResult.content;
let editorConfig = this.configurationService.getValue<any>();
if (editorConfig.editor.insertSpaces) {
content = content.replace(/(\n)(\t+)/g, (_, s1, s2) => s1 + strings.repeat(' ', s2.length * editorConfig.editor.tabSize));
@@ -2445,14 +2509,23 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
templateId?: string;
autoDetect: boolean;
};
this.telemetryService.publicLog2<TaskServiceEvent, TaskServiceTemplateClassification>('taskService.template', {
templateId: pickTemplateResult.id,
autoDetect: pickTemplateResult.autoDetect
});
}
if (!fileExists && content) {
return this.textFileService.create(resource, content).then((result): URI => {
this.telemetryService.publicLog2<TaskServiceEvent, TaskServiceTemplateClassification>('taskService.template', {
templateId: selection.id,
autoDetect: selection.autoDetect
});
return result.resource;
});
});
} else if (fileExists && (tasksExistInFile || content)) {
if (content) {
this.configurationService.updateValue('tasks', json.parse(content), target);
}
return stat?.resource;
}
return undefined;
}).then((resource) => {
if (!resource) {
return;
@@ -2488,10 +2561,25 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (this.isTaskEntry(selection)) {
this.configureTask(selection.task);
} else {
this.openTaskFile(selection.folder.toResource('.vscode/tasks.json'));
this.openTaskFile(selection.folder.toResource('.vscode/tasks.json'), TaskSourceKind.Workspace);
}
}
public getTaskDescription(task: Task): string | undefined {
let description: string | undefined;
if (task._source.kind === TaskSourceKind.User) {
description = nls.localize('taskQuickPick.userSettings', 'User Settings');
} else if (task._source.kind === TaskSourceKind.WorkspaceFile) {
description = task.getWorkspaceFileName();
} else if (this.needsFolderQualification()) {
let workspaceFolder = task.getWorkspaceFolder();
if (workspaceFolder) {
description = workspaceFolder.name;
}
}
return description;
}
private async runConfigureTasks(): Promise<void> {
if (!this.canRunCommand()) {
return undefined;
@@ -2520,7 +2608,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (tasks.length > 0) {
tasks = tasks.sort((a, b) => a._label.localeCompare(b._label));
for (let task of tasks) {
entries.push({ label: task._label, task });
entries.push({ label: task._label, task, description: this.getTaskDescription(task) });
if (!ContributedTask.is(task)) {
needsCreateOrOpen = false;
}
@@ -2541,7 +2629,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (tasks.length > 0) {
tasks = tasks.slice().sort((a, b) => a._label.localeCompare(b._label));
for (let i = 0; i < tasks.length; i++) {
let entry: TaskQuickPickEntryType = { label: tasks[i]._label, task: tasks[i], description: folder.name };
let entry: TaskQuickPickEntryType = { label: tasks[i]._label, task: tasks[i], description: this.getTaskDescription(tasks[i]) };
if (i === 0) {
entries.push({ type: 'separator', label: folder.name });
}
@@ -2633,7 +2721,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (!InMemoryTask.is(task)) {
this.customize(task, { group: { kind: 'build', isDefault: true } }, true).then(() => {
if (selectedTask && (task !== selectedTask) && !InMemoryTask.is(selectedTask)) {
this.customize(selectedTask, { group: 'build' }, true);
this.customize(selectedTask, { group: 'build' }, false);
}
});
}
@@ -2684,7 +2772,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (!InMemoryTask.is(task)) {
this.customize(task, { group: { kind: 'test', isDefault: true } }, true).then(() => {
if (selectedTask && (task !== selectedTask) && !InMemoryTask.is(selectedTask)) {
this.customize(selectedTask, { group: 'test' }, true);
this.customize(selectedTask, { group: 'test' }, false);
}
});
}