From 5ae87d2cface055985691ee122daa09b44b66b5c Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:42:21 +0200 Subject: [PATCH] Fix type validation for workflow inputs --- .../rules/InputTypeValidationRule.ts | 15 +++++-- server/packages/server-common/src/utils.ts | 8 ++++ shared/src/requestsDefinitions.ts | 41 ++++++++++++------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/server/gx-workflow-ls-format2/src/validation/rules/InputTypeValidationRule.ts b/server/gx-workflow-ls-format2/src/validation/rules/InputTypeValidationRule.ts index 1a759bb..56c6e44 100644 --- a/server/gx-workflow-ls-format2/src/validation/rules/InputTypeValidationRule.ts +++ b/server/gx-workflow-ls-format2/src/validation/rules/InputTypeValidationRule.ts @@ -1,5 +1,5 @@ -import { ValidationRule } from "@gxwf/server-common/src/languageTypes"; -import { isCompatibleType } from "@gxwf/server-common/src/utils"; +import { ValidationRule, WorkflowDataType } from "@gxwf/server-common/src/languageTypes"; +import { isCompatibleType, isWorkflowDataType } from "@gxwf/server-common/src/utils"; import { Diagnostic, DiagnosticSeverity } from "vscode-languageserver-types"; import { GxFormat2WorkflowDocument } from "../../gxFormat2WorkflowDocument"; @@ -16,13 +16,22 @@ export class InputTypeValidationRule implements ValidationRule { inputNodes.forEach((input) => { const inputName = String(input.keyNode.value); const inputType = documentContext.nodeManager.getPropertyValueByName(input, "type") as string; + + if (!isWorkflowDataType(inputType)) { + result.push({ + message: `Input '${inputName}' has an invalid type. Expected a valid workflow data type but found '${inputType}'.`, + range: documentContext.nodeManager.getNodeRange(input), + severity: this.severity, + }); + } + const defaultValueNode = documentContext.nodeManager.getPropertyNodeByName(input, "default"); const defaultValue = defaultValueNode?.valueNode?.value; const defaultValueType = typeof defaultValue; if (inputType && defaultValue) { - const defaultTypeMatchesValue = isCompatibleType(inputType, defaultValueType); + const defaultTypeMatchesValue = isCompatibleType(inputType as WorkflowDataType, defaultValueType); if (!defaultTypeMatchesValue) { result.push({ message: `Input '${inputName}' default value has invalid type. Expected '${inputType}' but found '${defaultValueType}'.`, diff --git a/server/packages/server-common/src/utils.ts b/server/packages/server-common/src/utils.ts index c82ca09..8019952 100644 --- a/server/packages/server-common/src/utils.ts +++ b/server/packages/server-common/src/utils.ts @@ -1,3 +1,4 @@ +import { workflowDataTypes } from "../../../../shared/src/requestsDefinitions"; import { WorkflowDataType } from "./languageTypes"; /** @@ -32,3 +33,10 @@ export function isCompatibleType(expectedType: WorkflowDataType, actualType: str } return isCompatible; } + +export function isWorkflowDataType(type?: string): type is WorkflowDataType { + if (!type) { + return false; + } + return type in workflowDataTypes; +} diff --git a/shared/src/requestsDefinitions.ts b/shared/src/requestsDefinitions.ts index 90bd7a3..633b830 100644 --- a/shared/src/requestsDefinitions.ts +++ b/shared/src/requestsDefinitions.ts @@ -28,20 +28,33 @@ export interface TargetWorkflowDocumentParams { uri: string; } -export type WorkflowDataType = - | "color" //TODO: this type seems to be missing in format2 schema - | "null" - | "boolean" - | "int" - | "long" - | "float" - | "double" - | "string" - | "integer" - | "text" - | "File" - | "data" - | "collection"; +/** + * This contains all the supported data types for workflow inputs. + * + * **Important**: This definition must be kept in sync with the schema definition. + * + * Note: Is defined as a const object to be used as a map and to be able to use the keys as a union type. + * This way we can maintain a single source of truth for the supported data types and generate WorkflowDataType + * type dynamically from it. + */ +export const workflowDataTypes = { + boolean: true, + collection: true, + color: true, //TODO: this type seems to be missing in format2 schema + data: true, + double: true, + File: true, + float: true, + int: true, + integer: true, + long: true, + null: true, + string: true, + text: true, +} as const; + +// Extract the keys of the object to form the union type +export type WorkflowDataType = keyof typeof workflowDataTypes; export interface WorkflowInput { name: string;