From ff6221bb85aa9bc39601ddec184f9b17629359fd Mon Sep 17 00:00:00 2001 From: Andrii Chebukin Date: Sun, 8 Dec 2024 00:53:31 +0400 Subject: [PATCH] Simplified `isAssignableWithUnwrap` implementation --- .../ReflectionHelper.fs | 15 +++++++-------- src/FSharp.Data.GraphQL.Shared/Validation.fs | 18 +++++++++--------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/FSharp.Data.GraphQL.Server/ReflectionHelper.fs b/src/FSharp.Data.GraphQL.Server/ReflectionHelper.fs index 26c2aed9..14eb7d32 100644 --- a/src/FSharp.Data.GraphQL.Server/ReflectionHelper.fs +++ b/src/FSharp.Data.GraphQL.Server/ReflectionHelper.fs @@ -149,7 +149,7 @@ module internal ReflectionHelper = ty.GetGenericArguments().[0] else ty - let isAssignableWithUnwrap (from: Type) (``to``: Type) = + let rec isAssignableWithUnwrap (from: Type) (``to``: Type) = let checkCollections (from: Type) (``to``: Type) = if @@ -176,17 +176,16 @@ module internal ReflectionHelper = from.GetGenericArguments()[0] else from let actualTo = - if ``to``.FullName.StartsWith OptionTypeName || ``to``.FullName.StartsWith ValueOptionTypeName then + if ``to``.FullName.StartsWith OptionTypeName || + ``to``.FullName.StartsWith ValueOptionTypeName + then ``to``.GetGenericArguments()[0] else ``to`` let result = actualFrom.IsAssignableTo actualTo || checkCollections actualFrom actualTo - if result then result - else - if actualFrom.FullName.StartsWith OptionTypeName || actualFrom.FullName.StartsWith ValueOptionTypeName then - let actualFrom = actualFrom.GetGenericArguments()[0] - actualFrom.IsAssignableTo actualTo || checkCollections actualFrom actualTo - else result + if result then true + elif actualFrom <> from || actualTo <> ``to`` then isAssignableWithUnwrap actualFrom actualTo + else false let matchConstructor (t: Type) (fields: string []) = if FSharpType.IsRecord(t, true) then FSharpValue.PreComputeRecordConstructorInfo(t, true) diff --git a/src/FSharp.Data.GraphQL.Shared/Validation.fs b/src/FSharp.Data.GraphQL.Shared/Validation.fs index bd078ce8..de516a3e 100644 --- a/src/FSharp.Data.GraphQL.Shared/Validation.fs +++ b/src/FSharp.Data.GraphQL.Shared/Validation.fs @@ -274,7 +274,9 @@ module Ast = |> ValueOption.map _.TypeCondition |> ValueOption.defaultValue x.ParentType - let private tryFindInArrayOption (finder : 'T -> bool) = ValueOption.ofOption >> ValueOption.bind (Array.tryFind finder >> ValueOption.ofOption) + let private tryFindInArrayOption (finder : 'T -> bool) = + ValueOption.ofOption + >> ValueOption.bind (Array.tryFind finder >> ValueOption.ofOption) let private onAllSelections (ctx : ValidationContext) (onSelection : SelectionInfo -> ValidationResult) = let rec traverseSelections selection = @@ -360,7 +362,9 @@ module Ast = |> ValueOption.defaultValue List.empty | FragmentSpread fragSpread -> voption { - let! fragDef = ctx.FragmentDefinitions |> List.tryFind (fun def -> def.Name.IsSome && def.Name.Value = fragSpread.Name) + let! fragDef = + ctx.FragmentDefinitions + |> List.tryFind (fun def -> def.Name.IsSome && def.Name.Value = fragSpread.Name) let! typeCondition = fragDef.TypeCondition let! fragType = ctx.Schema.TryGetTypeByName typeCondition let fragType = Spread (fragSpread.Name, fragSpread.Directives, fragType) @@ -898,10 +902,6 @@ module Ast = |> ValidationResult.collect (checkFragmentSpreadIsPossibleInSelection)) let private checkInputValue (schemaInfo : SchemaInfo) (variables : VariableDefinition list option) (selection : SelectionInfo) = - let rec getFieldMap (fields : (string * IntrospectionTypeRef) seq) : Map = - (Map.empty, fields) - ||> Seq.fold (fun acc (name, tref) -> Map.add name tref acc) - let rec checkIsCoercible (tref : IntrospectionTypeRef) (argName : string) (value : InputValue) = let canNotCoerce = AstError.AsResult ( @@ -954,8 +954,7 @@ module Ast = let fieldMap = itype.InputFields |> Option.defaultValue [||] - |> Array.map (fun x -> x.Name, x.Type) - |> getFieldMap + |> Array.fold (fun acc inputVal -> Map.add inputVal.Name inputVal.Type acc) Map.empty let canCoerceFields = fieldMap |> ValidationResult.collect (fun kvp -> @@ -1401,7 +1400,8 @@ module Ast = | ValueSome operationName, _ -> AstError.AsResult $"A variable '$%s{varDef.VariableName}' is not used in operation '%s{operationName}'. Every variable must be used." - | ValueNone, _ -> AstError.AsResult $"A variable '$%s{varDef.VariableName}' is not used in operation. Every variable must be used.") + | ValueNone, _ -> + AstError.AsResult $"A variable '$%s{varDef.VariableName}' is not used in operation. Every variable must be used.") | _ -> Success) let rec private areTypesCompatible (variableTypeRef : IntrospectionTypeRef) (locationTypeRef : IntrospectionTypeRef) =