Skip to content

Commit

Permalink
update task schema for Theia extensions & plugins
Browse files Browse the repository at this point in the history
- With this change, Theia processes task definitions contributed by extensions and plugins, and updates the task schema.
- resolves #6485

Signed-off-by: Liang Huang <[email protected]>
  • Loading branch information
Liang Huang committed Nov 7, 2019
1 parent 0e16fe0 commit 3ba3520
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 80 deletions.
11 changes: 10 additions & 1 deletion packages/cpp/src/browser/cpp-task-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,16 @@ export class CppTaskProvider implements TaskContribution, TaskProvider, TaskReso
source: 'cpp',
properties: {
required: ['label'],
all: ['label']
all: ['label'],
schema: {
type: CPP_BUILD_TASK_TYPE_KEY,
required: ['label'],
properties: {
label: {
type: 'string'
}
}
}
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@ export class TheiaPluginScanner implements PluginScanner {
source: pluginName,
properties: {
required: definitionContribution.required,
all: propertyKeys
all: propertyKeys,
schema: definitionContribution
}
};
}
Expand Down
21 changes: 19 additions & 2 deletions packages/task/src/browser/task-definition-registry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,32 @@ describe('TaskDefinitionRegistry', () => {
required: ['extensionType'],
properties: {
required: ['extensionType'],
all: ['extensionType', 'taskLabel']
all: ['extensionType', 'taskLabel'],
schema: {
type: 'extA',
required: ['extensionType'],
properties: {
extensionType: {},
taskLabel: {}
}
}
}
};
const definitonContributionB = {
taskType: 'extA',
source: 'extA',
properties: {
required: ['extensionType', 'taskLabel', 'taskDetailedLabel'],
all: ['extensionType', 'taskLabel', 'taskDetailedLabel']
all: ['extensionType', 'taskLabel', 'taskDetailedLabel'],
schema: {
type: 'extA',
required: ['extensionType', 'taskLabel', 'taskDetailedLabel'],
properties: {
extensionType: {},
taskLabel: {},
taskDetailedLabel: {}
}
}
}
};

Expand Down
175 changes: 99 additions & 76 deletions packages/task/src/browser/task-schema-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,41 @@ export class TaskSchemaUpdater {
return Array.from(allTypes.values()).sort();
}

private updateSchemasForRegisteredTasks(): void {
customizedDetectedTasks.length = 0;
const definitions = this.taskDefinitionRegistry.getAll();
definitions.forEach(def => {
const customizedDetectedTask = {
type: 'object',
required: ['type'],
properties: {}
} as IJSONSchema;
const taskType = {
...defaultTaskType,
enum: [def.taskType],
default: def.taskType,
description: 'The task type to customize'
};
customizedDetectedTask.properties!.type = taskType;
def.properties.all.forEach(taskProp => {
if (!!def.properties.required.find(requiredProp => requiredProp === taskProp)) { // property is mandatory
customizedDetectedTask.required!.push(taskProp);
}
customizedDetectedTask.properties![taskProp] = { ...def.properties.schema.properties![taskProp] };
});
customizedDetectedTask.properties!.problemMatcher = problemMatcher;
customizedDetectedTask.properties!.options = commandOptionsSchema;
customizedDetectedTasks.push(customizedDetectedTask);
});

taskConfigurationSchema.oneOf!.length = 1;
taskConfigurationSchema.oneOf!.push(...customizedDetectedTasks);
}

/** Returns the task's JSON schema */
getTaskSchema(): IJSONSchema {
return {
type: 'object',
properties: {
tasks: {
type: 'array',
Expand All @@ -103,11 +135,8 @@ export class TaskSchemaUpdater {
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.updateSchemasForRegisteredTasks();
this.update();
}
}
Expand Down Expand Up @@ -160,80 +189,74 @@ const commandOptionsSchema: IJSONSchema = {
};

const problemMatcherNames: string[] = [];
const supportedTaskTypes = ['shell', 'process']; // default types that Theia supports
const taskConfigurationSchema: IJSONSchema = {
$id: taskSchemaId,
const defaultTaskTypes = ['shell', 'process'];
const supportedTaskTypes = [...defaultTaskTypes];
const taskLabel = {
type: 'string',
description: 'A unique string that identifies the task that is also used as task\'s user interface label'
};
const defaultTaskType = {
type: 'string',
enum: supportedTaskTypes,
default: defaultTaskTypes[0],
description: 'Determines what type of process will be used to execute the task. Only shell types will have output shown on the user interface'
};
const commandAndArgs = {
command: commandSchema,
args: commandArgSchema,
options: commandOptionsSchema
};
const problemMatcher = {
oneOf: [
{
allOf: [
{
type: 'object',
required: ['type'],
properties: {
label: {
type: 'string',
description: 'A unique string that identifies the task that is also used as task\'s user interface label'
},
type: {
type: 'string',
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'
},
command: commandSchema,
args: commandArgSchema,
options: commandOptionsSchema,
windows: {
type: 'object',
description: 'Windows specific command configuration that overrides the command, args, and options',
properties: {
command: commandSchema,
args: commandArgSchema,
options: commandOptionsSchema
}
},
osx: {
type: 'object',
description: 'MacOS specific command configuration that overrides the command, args, and options',
properties: {
command: commandSchema,
args: commandArgSchema,
options: commandOptionsSchema
}
},
linux: {
type: 'object',
description: 'Linux specific command configuration that overrides the default command, args, and options',
properties: {
command: commandSchema,
args: commandArgSchema,
options: commandOptionsSchema
}
},
problemMatcher: {
oneOf: [
{
type: 'string',
description: 'Name of the problem matcher to parse the output of the task',
enum: problemMatcherNames
},
{
type: 'object',
description: 'User defined problem matcher(s) to parse the output of the task',
},
{
type: 'array',
description: 'Name(s) of the problem matcher(s) to parse the output of the task',
items: {
type: 'string',
enum: problemMatcherNames
}
}
]
}
}
}
]
type: 'string',
description: 'Name of the problem matcher to parse the output of the task',
enum: problemMatcherNames
},
{
type: 'object',
description: 'User defined problem matcher(s) to parse the output of the task',
},
{
type: 'array',
description: 'Name(s) of the problem matcher(s) to parse the output of the task',
items: {
type: 'string',
enum: problemMatcherNames
}
}
]
};

const processTaskConfigurationSchema: IJSONSchema = {
type: 'object',
required: ['type', 'label', 'command'],
properties: {
label: taskLabel,
type: defaultTaskType,
...commandAndArgs,
windows: {
type: 'object',
description: 'Windows specific command configuration that overrides the command, args, and options',
properties: commandAndArgs
},
osx: {
type: 'object',
description: 'MacOS specific command configuration that overrides the command, args, and options',
properties: commandAndArgs
},
linux: {
type: 'object',
description: 'Linux specific command configuration that overrides the default command, args, and options',
properties: commandAndArgs
},
problemMatcher
}
};

const customizedDetectedTasks: IJSONSchema[] = [];

const taskConfigurationSchema: IJSONSchema = {
$id: taskSchemaId,
oneOf: [processTaskConfigurationSchema, ...customizedDetectedTasks]
};
2 changes: 2 additions & 0 deletions packages/task/src/common/task-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
********************************************************************************/

import { JsonRpcServer } from '@theia/core/lib/common/messaging/proxy-factory';
import { IJSONSchema } from '@theia/core/lib/common/json-schema';
import { ProblemMatcher, ProblemMatch, WatchingPattern } from './problem-matcher-protocol';

export const taskPath = '/services/task';
Expand Down Expand Up @@ -133,6 +134,7 @@ export interface TaskDefinition {
properties: {
required: string[];
all: string[];
schema: IJSONSchema;
}
}

Expand Down

0 comments on commit 3ba3520

Please sign in to comment.