Skip to content

Commit 907a9c2

Browse files
task: make required optional
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 <vincent.fugnitto@ericsson.com>
1 parent 43a6b62 commit 907a9c2

File tree

7 files changed

+20
-15
lines changed

7 files changed

+20
-15
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<a name="breaking_changes_1.18.0">[Breaking Changes:](#breaking_changes_1.18.0)</a>
88

99
- [core] added `BreadcrumbsRendererFactory` to constructor arguments of `DockPanelRenderer` and `ToolbarAwareTabBar`. [#9920](https://github.com/eclipse-theia/theia/pull/9920)
10+
- [task] `TaskDefinition.properties.required` is now optional to align with the specification [#10015](https://github.com/eclipse-theia/theia/pull/10015)
1011

1112
## v1.17.2 - 9/1/2021
1213

packages/plugin-ext/src/hosted/node/scanners/scanner-theia.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ export class TheiaPluginScanner implements PluginScanner {
698698
taskType: definitionContribution.type,
699699
source: pluginName,
700700
properties: {
701-
required: definitionContribution.required,
701+
required: definitionContribution.required || [],
702702
all: propertyKeys,
703703
schema: definitionContribution
704704
}

packages/task/src/browser/provided-task-configurations.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,12 @@ export class ProvidedTaskConfigurations {
101101
let highest = -1;
102102
const tasks = await this.getTasks(token);
103103
for (const task of tasks) { // find detected tasks that match the `definition`
104-
let score = 0;
105-
if (!definition.properties.required.every(requiredProp => customization[requiredProp] !== undefined)) {
104+
const required = definition.properties.required || [];
105+
if (!required.every(requiredProp => customization[requiredProp] !== undefined)) {
106106
continue;
107107
}
108-
score += definition.properties.required.length; // number of required properties
109-
const requiredProps = new Set(definition.properties.required);
108+
let score = required.length; // number of required properties
109+
const requiredProps = new Set(required);
110110
// number of optional properties
111111
score += definition.properties.all.filter(p => !requiredProps.has(p) && customization[p] !== undefined).length;
112112
if (score >= highest) {

packages/task/src/browser/task-configurations.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,9 @@ export class TaskConfigurations implements Disposable {
249249
if (hasCustomization) {
250250
const taskDefinition = this.taskDefinitionRegistry.getDefinition(taskConfig);
251251
if (taskDefinition) {
252-
const cus = customizationByType.filter(customization =>
253-
taskDefinition.properties.required.every(rp => customization[rp] === taskConfig[rp])
254-
)[0]; // Only support having one customization per task
255-
return cus;
252+
const required = taskDefinition.properties.required || [];
253+
// Only support having one customization per task.
254+
return customizationByType.find(customization => required.every(property => customization[property] === taskConfig[property]));
256255
}
257256
}
258257
return undefined;

packages/task/src/browser/task-definition-registry.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ export class TaskDefinitionRegistry {
7171
let matchedDefinition: TaskDefinition | undefined;
7272
let highest = -1;
7373
for (const def of definitions) {
74-
let score = 0;
75-
if (!def.properties.required.every(requiredProp => taskConfiguration[requiredProp] !== undefined)) {
74+
const required = def.properties.required || [];
75+
if (!required.every(requiredProp => taskConfiguration[requiredProp] !== undefined)) {
7676
continue;
7777
}
78-
score += def.properties.required.length; // number of required properties
79-
const requiredProps = new Set(def.properties.required);
78+
let score = required.length; // number of required properties
79+
const requiredProps = new Set(required);
8080
// number of optional properties
8181
score += def.properties.all.filter(p => !requiredProps.has(p) && taskConfiguration[p] !== undefined).length;
8282
if (score > highest) {

packages/task/src/browser/task-schema-updater.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,9 @@ export class TaskSchemaUpdater implements JsonSchemaContribution {
168168
description: 'The task type to customize'
169169
};
170170
customizedDetectedTask.properties!.type = taskType;
171+
const required = def.properties.required || [];
171172
def.properties.all.forEach(taskProp => {
172-
if (!!def.properties.required.find(requiredProp => requiredProp === taskProp)) { // property is mandatory
173+
if (required.find(requiredProp => requiredProp === taskProp)) { // property is mandatory
173174
customizedDetectedTask.required!.push(taskProp);
174175
}
175176
customizedDetectedTask.properties![taskProp] = { ...def.properties.schema.properties![taskProp] };

packages/task/src/common/task-protocol.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,11 @@ export interface TaskDefinition {
274274
taskType: string;
275275
source: string;
276276
properties: {
277-
required: string[];
277+
/**
278+
* Should be treated as an empty array if omitted.
279+
* https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.5.3
280+
*/
281+
required?: string[];
278282
all: string[];
279283
schema: IJSONSchema;
280284
}

0 commit comments

Comments
 (0)