Skip to content

Commit

Permalink
Introduce a token to scope contributed tasks
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Mäder <tmader@redhat.com>
  • Loading branch information
tsmaeder committed Jul 15, 2020
1 parent a1ea230 commit a0e635a
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 95 deletions.
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

0 comments on commit a0e635a

Please sign in to comment.