Skip to content

Commit

Permalink
task: make required optional
Browse files Browse the repository at this point in the history
The commit makes `TaskDefinition.properties.required` optional based on
the json schema validation definition. Previously, if an extension
defines a schema that omits the `required` property the application will
throw errors and fail to display the menu. The change treats the missing
`required` property as an empty array as per the spec.

Signed-off-by: vince-fugnitto <[email protected]>
  • Loading branch information
vince-fugnitto committed Aug 31, 2021
1 parent a7d63a0 commit 4c854ba
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ export class TheiaPluginScanner implements PluginScanner {
taskType: definitionContribution.type,
source: pluginName,
properties: {
required: definitionContribution.required,
required: definitionContribution.required || [],
all: propertyKeys,
schema: definitionContribution
}
Expand Down
7 changes: 4 additions & 3 deletions packages/task/src/browser/provided-task-configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,12 @@ export class ProvidedTaskConfigurations {
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)) {
const required = definition.properties.required || [];
if (!required.every(requiredProp => customization[requiredProp] !== undefined)) {
continue;
}
score += definition.properties.required.length; // number of required properties
const requiredProps = new Set(definition.properties.required);
score += required.length; // number of required properties
const requiredProps = new Set(required);
// number of optional properties
score += definition.properties.all.filter(p => !requiredProps.has(p) && customization[p] !== undefined).length;
if (score >= highest) {
Expand Down
2 changes: 1 addition & 1 deletion packages/task/src/browser/task-configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export class TaskConfigurations implements Disposable {
const taskDefinition = this.taskDefinitionRegistry.getDefinition(taskConfig);
if (taskDefinition) {
const cus = customizationByType.filter(customization =>
taskDefinition.properties.required.every(rp => customization[rp] === taskConfig[rp])
taskDefinition.properties.required?.every(rp => customization[rp] === taskConfig[rp])
)[0]; // Only support having one customization per task
return cus;
}
Expand Down
7 changes: 4 additions & 3 deletions packages/task/src/browser/task-definition-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ export class TaskDefinitionRegistry {
let highest = -1;
for (const def of definitions) {
let score = 0;
if (!def.properties.required.every(requiredProp => taskConfiguration[requiredProp] !== undefined)) {
const required = def.properties.required || [];
if (!required.every(requiredProp => taskConfiguration[requiredProp] !== undefined)) {
continue;
}
score += def.properties.required.length; // number of required properties
const requiredProps = new Set(def.properties.required);
score += required.length; // number of required properties
const requiredProps = new Set(required);
// number of optional properties
score += def.properties.all.filter(p => !requiredProps.has(p) && taskConfiguration[p] !== undefined).length;
if (score > highest) {
Expand Down
3 changes: 2 additions & 1 deletion packages/task/src/browser/task-schema-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,9 @@ export class TaskSchemaUpdater implements JsonSchemaContribution {
description: 'The task type to customize'
};
customizedDetectedTask.properties!.type = taskType;
const required = def.properties.required || [];
def.properties.all.forEach(taskProp => {
if (!!def.properties.required.find(requiredProp => requiredProp === taskProp)) { // property is mandatory
if (required.find(requiredProp => requiredProp === taskProp)) { // property is mandatory
customizedDetectedTask.required!.push(taskProp);
}
customizedDetectedTask.properties![taskProp] = { ...def.properties.schema.properties![taskProp] };
Expand Down
6 changes: 5 additions & 1 deletion packages/task/src/common/task-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,11 @@ export interface TaskDefinition {
taskType: string;
source: string;
properties: {
required: string[];
/**
* Should be treated as an empty array if omitted.
* https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.5.3
*/
required?: string[];
all: string[];
schema: IJSONSchema;
}
Expand Down

0 comments on commit 4c854ba

Please sign in to comment.