Skip to content

Commit

Permalink
update support task types in the task schema
Browse files Browse the repository at this point in the history
- Some vscode extensions, after being installed as Theia plugins, make contributions to task definitions, while Theia's task schema does not get updated. This results in situations where wrong warnings are displayed even if valid task types are entered into the editor. This change fixes this bug.
- fixes #6478

Signed-off-by: Liang Huang <[email protected]>
  • Loading branch information
Liang Huang authored and elaihau committed Nov 4, 2019
1 parent 6aa3b0d commit bc11e2c
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 13 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## v0.13.0

Breaking changes:

- [task] changed `TaskSchemaUpdater.update()` from asynchronous to synchronous [#6483](https://github.com/eclipse-theia/theia/pull/6483)

## v0.12.0

- [cli] added explicit `yargs` dependency [#6443](https://github.com/eclipse-theia/theia/pull/6443)
Expand Down
12 changes: 12 additions & 0 deletions packages/task/src/browser/task-definition-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ export class TaskDefinitionRegistry {
return this.onDidUnregisterTaskDefinitionEmitter.event;
}

/**
* Returns all task definitions that are registered
* @return the task definitions that are registered
*/
getAll(): TaskDefinition[] {
const all: TaskDefinition[] = [];
for (const definitions of this.definitions.values()) {
all.push(...definitions);
}
return all;
}

/**
* Finds the task definition(s) from the registry with the given `taskType`.
*
Expand Down
52 changes: 40 additions & 12 deletions packages/task/src/browser/task-schema-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import { InMemoryResources, deepClone } from '@theia/core/lib/common';
import { IJSONSchema } from '@theia/core/lib/common/json-schema';
import { inputsSchema } from '@theia/variable-resolver/lib/browser/variable-input-schema';
import URI from '@theia/core/lib/common/uri';
import { TaskService } from './task-service';
import { ProblemMatcherRegistry } from './task-problem-matcher-registry';
import { TaskDefinitionRegistry } from './task-definition-registry';
import { TaskServer } from '../common';

export const taskSchemaId = 'vscode://schemas/tasks';

Expand All @@ -32,22 +33,29 @@ export class TaskSchemaUpdater {
@inject(InMemoryResources)
protected readonly inmemoryResources: InMemoryResources;

@inject(TaskService)
protected readonly taskService: TaskService;

@inject(ProblemMatcherRegistry)
protected readonly problemMatcherRegistry: ProblemMatcherRegistry;

@inject(TaskDefinitionRegistry)
protected readonly taskDefinitionRegistry: TaskDefinitionRegistry;

@inject(TaskServer)
protected readonly taskServer: TaskServer;

@postConstruct()
protected init(): void {
this.updateProblemMatcherNames();
this.updateSupportedTaskTypes();
// update problem matcher names in the task schema every time a problem matcher is added or disposed
this.problemMatcherRegistry.onDidChangeProblemMatcher(() => this.updateProblemMatcherNames());
// update supported task types in the task schema every time a task definition is registered or removed
this.taskDefinitionRegistry.onDidRegisterTaskDefinition(() => this.updateSupportedTaskTypes());
this.taskDefinitionRegistry.onDidUnregisterTaskDefinition(() => this.updateSupportedTaskTypes());
}

async update(): Promise<void> {
update(): void {
const taskSchemaUri = new URI(taskSchemaId);
const schemaContent = await this.getTaskSchema();
const schemaContent = this.getStrigifiedTaskSchema();
try {
this.inmemoryResources.update(taskSchemaUri, schemaContent);
} catch (e) {
Expand All @@ -59,8 +67,17 @@ export class TaskSchemaUpdater {
}
}

private async getTaskSchema(): Promise<string> {
const taskSchema = {
/** Returns an array of task types that are registered, including the default types */
async getRegisteredTaskTypes(): Promise<string[]> {
const serverSupportedTypes = await this.taskServer.getRegisteredTaskTypes();
const browserSupportedTypes = this.taskDefinitionRegistry.getAll().map(def => def.taskType);
const allTypes = new Set([...serverSupportedTypes, ...browserSupportedTypes]);
return Array.from(allTypes.values()).sort();
}

/** Returns the task's JSON schema */
getTaskSchema(): IJSONSchema {
return {
properties: {
tasks: {
type: 'array',
Expand All @@ -71,9 +88,11 @@ export class TaskSchemaUpdater {
inputs: inputsSchema.definitions!.inputs
}
};
const taskTypes = await this.taskService.getRegisteredTaskTypes();
taskSchema.properties.tasks.items.oneOf![0].allOf![0].properties!.type.enum = taskTypes;
return JSON.stringify(taskSchema);
}

/** Returns the task's JSON schema as a string */
private getStrigifiedTaskSchema(): string {
return JSON.stringify(this.getTaskSchema());
}

/** Gets the most up-to-date names of problem matchers from the registry and update the task schema */
Expand All @@ -83,6 +102,14 @@ export class TaskSchemaUpdater {
problemMatcherNames.push(...matcherNames);
this.update();
}

/** Gets the most up-to-date names of task types Theia supports from the registry and update the task schema */
private async updateSupportedTaskTypes(): Promise<void> {
const allTypes = await this.getRegisteredTaskTypes();
supportedTaskTypes.length = 0;
supportedTaskTypes.push(...allTypes);
this.update();
}
}

const commandSchema: IJSONSchema = {
Expand Down Expand Up @@ -133,6 +160,7 @@ const commandOptionsSchema: IJSONSchema = {
};

const problemMatcherNames: string[] = [];
const supportedTaskTypes = ['shell', 'process']; // default types that Theia supports
const taskConfigurationSchema: IJSONSchema = {
$id: taskSchemaId,
oneOf: [
Expand All @@ -148,7 +176,7 @@ const taskConfigurationSchema: IJSONSchema = {
},
type: {
type: 'string',
enum: ['shell', 'process'],
enum: supportedTaskTypes,
default: 'shell',
description: 'Determines what type of process will be used to execute the task. Only shell types will have output shown on the user interface'
},
Expand Down
6 changes: 5 additions & 1 deletion packages/task/src/browser/task-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { TaskProviderRegistry, TaskResolverRegistry } from './task-contribution'
import { TaskDefinitionRegistry } from './task-definition-registry';
import { TaskNameResolver } from './task-name-resolver';
import { ProblemMatcherRegistry } from './task-problem-matcher-registry';
import { TaskSchemaUpdater } from './task-schema-updater';

export interface QuickPickProblemMatcherItem {
problemMatchers: NamedProblemMatcher[] | undefined;
Expand Down Expand Up @@ -128,6 +129,9 @@ export class TaskService implements TaskConfigurationClient {
@inject(TaskNameResolver)
protected readonly taskNameResolver: TaskNameResolver;

@inject(TaskSchemaUpdater)
protected readonly taskSchemaUpdater: TaskSchemaUpdater;

/**
* @deprecated To be removed in 0.5.0
*/
Expand Down Expand Up @@ -281,7 +285,7 @@ export class TaskService implements TaskConfigurationClient {

/** Returns an array of task types that are registered, including the default types */
getRegisteredTaskTypes(): Promise<string[]> {
return this.taskServer.getRegisteredTaskTypes();
return this.taskSchemaUpdater.getRegisteredTaskTypes();
}

/**
Expand Down

0 comments on commit bc11e2c

Please sign in to comment.