Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a token to scope contributed tasks #7996

Merged
merged 1 commit into from
Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/debug/src/browser/debug-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ export class DebugSessionManager {
return true;
}

const taskInfo = await this.taskService.runWorkspaceTask(workspaceFolderUri, taskName);
const taskInfo = await this.taskService.runWorkspaceTask(this.taskService.startUserAction(), workspaceFolderUri, taskName);
if (!checkErrors) {
return true;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/plugin-ext/src/main/browser/tasks-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,10 @@ export class TasksMainImpl implements TasksMain, Disposable {
return [];
}

const token: number = this.taskService.startUserAction();
const [configured, provided] = await Promise.all([
this.taskService.getConfiguredTasks(),
this.taskService.getProvidedTasks()
this.taskService.getConfiguredTasks(token),
this.taskService.getProvidedTasks(token)
]);
const result: TaskDto[] = [];
for (const tasks of [configured, provided]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('provided-task-configurations', () => {
}
});

const task = await container.get(ProvidedTaskConfigurations).getTask('test', 'task from test', 'test');
const task = await container.get(ProvidedTaskConfigurations).getTask(1, 'test', 'task from test', 'test');
assert.isOk(task);
assert.equal(task!.type, 'test');
assert.equal(task!.label, 'task from test');
Expand Down
71 changes: 44 additions & 27 deletions packages/task/src/browser/provided-task-configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { TaskConfiguration, TaskCustomization, TaskOutputPresentation, TaskConfi

@injectable()
export class ProvidedTaskConfigurations {

/**
* Map of source (name of extension, or path of root folder that the task config comes from) and `task config map`.
* For the second level of inner map, the key is task label.
Expand All @@ -35,36 +34,53 @@ export class ProvidedTaskConfigurations {
@inject(TaskDefinitionRegistry)
protected readonly taskDefinitionRegistry: TaskDefinitionRegistry;

private currentToken: number = 0;
private nextToken = 1;

startUserAction(): number {
return this.nextToken++;
}

/** returns a list of provided tasks */
async getTasks(): Promise<TaskConfiguration[]> {
const providers = await this.taskProviderRegistry.getProviders();
const providedTasks: TaskConfiguration[] = (await Promise.all(providers.map(p => p.provideTasks())))
.reduce((acc, taskArray) => acc.concat(taskArray), [])
.map(providedTask => {
const originalPresentation = providedTask.presentation || {};
return {
...providedTask,
presentation: {
...TaskOutputPresentation.getDefault(),
...originalPresentation
}
};
});
this.cacheTasks(providedTasks);
return providedTasks;
async getTasks(token: number): Promise<TaskConfiguration[]> {
await this.refreshTasks(token);
const tasks: TaskConfiguration[] = [];
for (const taskLabelMap of this.tasksMap!.values()) {
for (const taskScopeMap of taskLabelMap.values()) {
for (const task of taskScopeMap.values()) {
tasks.push(task);
}
}
}
return tasks;
}

/** returns the task configuration for a given source and label or undefined if none */
async getTask(source: string, taskLabel: string, scope: TaskConfigurationScope): Promise<TaskConfiguration | undefined> {
const task = this.getCachedTask(source, taskLabel, scope);
if (task) {
return task;
} else {
await this.getTasks();
return this.getCachedTask(source, taskLabel, scope);
protected async refreshTasks(token: number): Promise<void> {
if (token !== this.currentToken) {
this.currentToken = token;
const providers = await this.taskProviderRegistry.getProviders();
const providedTasks: TaskConfiguration[] = (await Promise.all(providers.map(p => p.provideTasks())))
.reduce((acc, taskArray) => acc.concat(taskArray), [])
.map(providedTask => {
const originalPresentation = providedTask.presentation || {};
return {
...providedTask,
presentation: {
...TaskOutputPresentation.getDefault(),
...originalPresentation
}
};
});
this.cacheTasks(providedTasks);
}
}

/** returns the task configuration for a given source and label or undefined if none */
async getTask(token: number, source: string, taskLabel: string, scope: TaskConfigurationScope): Promise<TaskConfiguration | undefined> {
await this.refreshTasks(token);
return this.getCachedTask(source, taskLabel, scope);
}

/**
* Finds the detected task for the given task customization.
* The detected task is considered as a "match" to the task customization if it has all the `required` properties.
Expand All @@ -73,15 +89,15 @@ export class ProvidedTaskConfigurations {
* @param customization the task customization
* @return the detected task for the given task customization. If the task customization is not found, `undefined` is returned.
*/
async getTaskToCustomize(customization: TaskCustomization, scope: TaskConfigurationScope): Promise<TaskConfiguration | undefined> {
async getTaskToCustomize(token: number, customization: TaskCustomization, scope: TaskConfigurationScope): Promise<TaskConfiguration | undefined> {
const definition = this.taskDefinitionRegistry.getDefinition(customization);
if (!definition) {
return undefined;
}

const matchedTasks: TaskConfiguration[] = [];
let highest = -1;
const tasks = await this.getTasks();
const tasks = await this.getTasks(token);
for (const task of tasks) { // find detected tasks that match the `definition`
let score = 0;
if (!definition.properties.required.every(requiredProp => customization[requiredProp] !== undefined)) {
Expand Down Expand Up @@ -123,6 +139,7 @@ export class ProvidedTaskConfigurations {
}

protected cacheTasks(tasks: TaskConfiguration[]): void {
this.tasksMap.clear();
for (const task of tasks) {
const label = task.label;
const source = task._source;
Expand Down
56 changes: 37 additions & 19 deletions packages/task/src/browser/quick-open-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class ConfigureTaskAction extends QuickOpenBaseAction {

async run(item?: QuickOpenItem): Promise<void> {
if (item instanceof TaskRunQuickOpenItem) {
this.taskService.configure(item.getTask());
this.taskService.configure(item.getToken(), item.getTask());
}
}

Expand Down Expand Up @@ -111,25 +111,29 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
@inject(LabelProvider)
protected readonly labelProvider: LabelProvider;

init(): Promise<void> {
return this.doInit(this.taskService.startUserAction());
}

/** Initialize this quick open model with the tasks. */
async init(): Promise<void> {
protected async doInit(token: number): Promise<void> {
const recentTasks = this.taskService.recentTasks;
const configuredTasks = await this.taskService.getConfiguredTasks();
const providedTasks = await this.taskService.getProvidedTasks();
const configuredTasks = await this.taskService.getConfiguredTasks(token);
const providedTasks = await this.taskService.getProvidedTasks(token);

const { filteredRecentTasks, filteredConfiguredTasks, filteredProvidedTasks } = this.getFilteredTasks(recentTasks, configuredTasks, providedTasks);
const isMulti: boolean = this.workspaceService.isMultiRootWorkspaceOpened;
this.items = [];
this.items.push(
...filteredRecentTasks.map((task, index) => {
const item = new TaskRunQuickOpenItem(task, this.taskService, isMulti, {
const item = new TaskRunQuickOpenItem(token, task, this.taskService, isMulti, {
groupLabel: index === 0 ? 'recently used tasks' : undefined,
showBorder: false
}, this.taskDefinitionRegistry, this.taskNameResolver, this.taskSourceResolver);
return item;
}),
...filteredConfiguredTasks.map((task, index) => {
const item = new TaskRunQuickOpenItem(task, this.taskService, isMulti, {
const item = new TaskRunQuickOpenItem(token, task, this.taskService, isMulti, {
groupLabel: index === 0 ? 'configured tasks' : undefined,
showBorder: (
filteredRecentTasks.length <= 0
Expand All @@ -140,7 +144,7 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
return item;
}),
...filteredProvidedTasks.map((task, index) => {
const item = new TaskRunQuickOpenItem(task, this.taskService, isMulti, {
const item = new TaskRunQuickOpenItem(token, task, this.taskService, isMulti, {
groupLabel: index === 0 ? 'detected tasks' : undefined,
showBorder: (
filteredRecentTasks.length <= 0 && filteredConfiguredTasks.length <= 0
Expand All @@ -156,7 +160,8 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
}

async open(): Promise<void> {
await this.init();
const token: number = this.taskService.startUserAction();
await this.doInit(token);
if (!this.items.length) {
this.items.push(new QuickOpenItem({
label: 'No task to run found. Configure Tasks...',
Expand Down Expand Up @@ -235,8 +240,10 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
this.actionProvider = undefined;
const isMulti: boolean = this.workspaceService.isMultiRootWorkspaceOpened;

const configuredTasks = await this.taskService.getConfiguredTasks();
const providedTasks = await this.taskService.getProvidedTasks();
const token: number = this.taskService.startUserAction();

const configuredTasks = await this.taskService.getConfiguredTasks(token);
const providedTasks = await this.taskService.getProvidedTasks(token);

// check if tasks.json exists. If not, display "Create tasks.json file from template"
// If tasks.json exists and empty, display 'Open tasks.json file'
Expand All @@ -248,6 +255,7 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
this.items.push(
...configs.map(taskConfig => {
const item = new TaskConfigureQuickOpenItem(
token,
taskConfig,
this.taskService,
this.taskNameResolver,
Expand All @@ -270,6 +278,7 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
this.items.push(
...configs.map((taskConfig, index) => {
const item = new TaskConfigureQuickOpenItem(
token,
taskConfig,
this.taskService,
this.taskNameResolver,
Expand Down Expand Up @@ -319,7 +328,8 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {

async runBuildOrTestTask(buildOrTestType: 'build' | 'test'): Promise<void> {
const shouldRunBuildTask = buildOrTestType === 'build';
await this.init();
const token: number = this.taskService.startUserAction();
await this.doInit(token);
if (this.items.length > 1 ||
this.items.length === 1 && (this.items[0] as TaskRunQuickOpenItem).getTask !== undefined) { // the item in `this.items` is not 'No tasks found'

Expand All @@ -337,9 +347,9 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
const scope = taskToRun._scope;

if (this.taskDefinitionRegistry && !!this.taskDefinitionRegistry.getDefinition(taskToRun)) {
this.taskService.run(taskToRun.source, taskToRun.label, scope);
this.taskService.run(token, taskToRun.source, taskToRun.label, scope);
} else {
this.taskService.run(taskToRun._source, taskToRun.label, scope);
this.taskService.run(token, taskToRun._source, taskToRun.label, scope);
}
return;
}
Expand All @@ -356,10 +366,11 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
return false;
}

this.init().then(() => {
this.doInit(token).then(() => {
// update the `tasks.json` file, instead of running the task itself
this.items = this.items.map((item: TaskRunQuickOpenItem) => {
const newItem = new ConfigureBuildOrTestTaskQuickOpenItem(
token,
item.getTask(),
this.taskService,
this.workspaceService.isMultiRootWorkspaceOpened,
Expand Down Expand Up @@ -466,6 +477,7 @@ export class QuickOpenTask implements QuickOpenModel, QuickOpenHandler {
export class TaskRunQuickOpenItem extends QuickOpenGroupItem {

constructor(
protected readonly token: number,
protected readonly task: TaskConfiguration,
protected taskService: TaskService,
protected isMulti: boolean,
Expand All @@ -485,6 +497,10 @@ export class TaskRunQuickOpenItem extends QuickOpenGroupItem {
return this.taskNameResolver.resolve(this.task);
}

getToken(): number {
return this.token;
}

getGroupLabel(): string {
return this.options.groupLabel || '';
}
Expand All @@ -500,9 +516,9 @@ export class TaskRunQuickOpenItem extends QuickOpenGroupItem {

const scope = this.task._scope;
if (this.taskDefinitionRegistry && !!this.taskDefinitionRegistry.getDefinition(this.task)) {
this.taskService.run(this.task.source || this.task._source, this.task.label, scope);
this.taskService.run(this.token, this.task.source || this.task._source, this.task.label, scope);
} else {
this.taskService.run(this.task._source, this.task.label, scope);
this.taskService.run(this.token, this.task._source, this.task.label, scope);
}
return true;
}
Expand All @@ -514,6 +530,7 @@ export class TaskRunQuickOpenItem extends QuickOpenGroupItem {

export class ConfigureBuildOrTestTaskQuickOpenItem extends TaskRunQuickOpenItem {
constructor(
protected readonly token: number,
protected readonly task: TaskConfiguration,
protected taskService: TaskService,
protected isMulti: boolean,
Expand All @@ -524,14 +541,14 @@ export class ConfigureBuildOrTestTaskQuickOpenItem extends TaskRunQuickOpenItem
protected readonly taskDefinitionRegistry: TaskDefinitionRegistry,
protected readonly taskSourceResolver: TaskSourceResolver
) {
super(task, taskService, isMulti, options, taskDefinitionRegistry, taskNameResolver, taskSourceResolver);
super(token, task, taskService, isMulti, options, taskDefinitionRegistry, taskNameResolver, taskSourceResolver);
}

run(mode: QuickOpenMode): boolean {
if (mode !== QuickOpenMode.OPEN) {
return false;
}
this.taskService.updateTaskConfiguration(this.task, { group: { kind: this.isBuildTask ? 'build' : 'test', isDefault: true } })
this.taskService.updateTaskConfiguration(this.token, this.task, { group: { kind: this.isBuildTask ? 'build' : 'test', isDefault: true } })
.then(() => {
if (this.task._scope) {
this.taskConfigurationManager.openConfiguration(this.task._scope);
Expand Down Expand Up @@ -559,6 +576,7 @@ export class TaskConfigureQuickOpenItem extends QuickOpenGroupItem {
protected taskDefinitionRegistry: TaskDefinitionRegistry;

constructor(
protected readonly token: number,
protected readonly task: TaskConfiguration,
protected readonly taskService: TaskService,
protected readonly taskNameResolver: TaskNameResolver,
Expand Down Expand Up @@ -587,7 +605,7 @@ export class TaskConfigureQuickOpenItem extends QuickOpenGroupItem {
if (mode !== QuickOpenMode.OPEN) {
return false;
}
this.taskService.configure(this.task);
this.taskService.configure(this.token, this.task);

return true;
}
Expand Down
Loading