From c1f0988dd3edb34f8c3cdaefed0f1c6d5ebe54e4 Mon Sep 17 00:00:00 2001 From: Andrii Chebukin Date: Mon, 18 Aug 2025 00:46:57 +0400 Subject: [PATCH 1/2] Eliminated unnecessary list allocations in `Validation.fs` --- .../ProvidedTypesHelper.fs | 2 +- src/FSharp.Data.GraphQL.Shared/Validation.fs | 47 ++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs b/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs index c24ab7a3..f94f327b 100644 --- a/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs +++ b/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs @@ -545,7 +545,7 @@ module internal Provider = |> List.choose (function FragmentField f when f.TypeCondition <> tref.Name.Value -> Some f | _ -> None) |> List.groupBy (fun field -> field.TypeCondition) |> List.map (fun (typeCondition, fields) -> - let conditionFields = fields |> List.distinctBy (fun x -> x.AliasOrName) |> List.map FragmentField + let conditionFields = fields |> Seq.distinctBy _.AliasOrName |> Seq.map FragmentField |> Seq.toList typeCondition, List.map (getPropertyMetadata typeCondition) conditionFields) let baseProperties = astFields diff --git a/src/FSharp.Data.GraphQL.Shared/Validation.fs b/src/FSharp.Data.GraphQL.Shared/Validation.fs index 72d84142..4a241a9b 100644 --- a/src/FSharp.Data.GraphQL.Shared/Validation.fs +++ b/src/FSharp.Data.GraphQL.Shared/Validation.fs @@ -90,13 +90,13 @@ module Ast = type MetaTypeFieldInfo = { Name : string; ArgumentNames : string[] } let private metaTypeFields = - [| + seq { { Name = "__type"; ArgumentNames = [| "name" |] } { Name = "__schema"; ArgumentNames = [||] } { Name = "__typename"; ArgumentNames = [||] } - |] - |> Array.map (fun x -> x.Name, x) - |> Map.ofArray + } + |> Seq.map (fun x -> x.Name, x) + |> Map.ofSeq let rec private tryGetSchemaTypeByRef (schemaTypes : Map) (tref : IntrospectionTypeRef) = match tref.Kind with @@ -436,8 +436,8 @@ module Ast = AstError.AsResult $"Operation '%s{name}' has %i{count} definitions. Each operation name must be unique.") let internal validateLoneAnonymousOperation (ctx : ValidationContext) = - let operations = ctx.OperationDefinitions |> List.map (fun x -> x.Definition) - let unamed = operations |> List.filter (fun x -> x.Name.IsNone) + let operations = ctx.OperationDefinitions |> List.map _.Definition + let unamed = operations |> List.filter _.Name.IsNone if unamed.Length = 0 then Success elif unamed.Length = 1 && operations.Length = 1 then @@ -529,7 +529,7 @@ module Ast = ) let rec private fieldsInSetCanMerge (set : SelectionInfo list) = - let fieldsForName = set |> List.groupBy (fun x -> x.AliasOrName) + let fieldsForName = set |> List.groupBy _.AliasOrName fieldsForName |> ValidationResult.collect (fun (aliasOrName, selectionSet) -> if selectionSet.Length < 2 then @@ -596,8 +596,9 @@ module Ast = |> ValidationResult.collect (fun arg -> let schemaArgumentNames = metaTypeFields.TryFind (selection.Field.Name) - |> Option.map (fun x -> x.ArgumentNames) - |> Option.defaultValue (selection.InputValues |> Array.map (fun x -> x.Name)) + |> ValueOption.ofOption + |> ValueOption.map _.ArgumentNames + |> ValueOption.defaultWith (fun () -> selection.InputValues |> Array.map _.Name) match schemaArgumentNames |> Array.tryFind (fun x -> x = arg.Name) with | Some _ -> Success | None -> @@ -633,7 +634,7 @@ module Ast = let rec private validateArgumentUniquenessInSelection (selection : SelectionInfo) = let validateArgs (fieldOrDirective : string) (path : FieldPath) (args : Argument list) = args - |> List.countBy (fun x -> x.Name) + |> List.countBy _.Name |> ValidationResult.collect (fun (name, length) -> if length > 1 then AstError.AsResult ( @@ -1019,7 +1020,7 @@ module Ast = match selection with | Field field -> let path = box field.AliasOrName :: path - let fieldDirectives = [ path, field.Directives |> List.map (fun x -> x.Name) |> Set.ofList ] + let fieldDirectives = [ path, field.Directives |> Seq.map _.Name |> Set.ofSeq ] let selectionSetDirectives = field.SelectionSet |> List.collect (getDistinctDirectiveNamesInSelection path) @@ -1028,12 +1029,12 @@ module Ast = | FragmentSpread spread -> [ path, spread.Directives - |> List.map (fun x -> x.Name) - |> Set.ofList + |> Seq.map _.Name + |> Set.ofSeq ] and private getDistinctDirectiveNamesInDefinition (path : FieldPath) (frag : Definition) : (FieldPath * Set) list = - let fragDirectives = [ path, frag.Directives |> List.map (fun x -> x.Name) |> Set.ofList ] + let fragDirectives = [ path, frag.Directives |> Seq.map _.Name |> Set.ofSeq ] let selectionSetDirectives = frag.SelectionSet |> List.collect (getDistinctDirectiveNamesInSelection path) @@ -1172,7 +1173,7 @@ module Ast = directivesValid @@ directivesValidInSelectionSet let internal validateDirectivesAreInValidLocations (ctx : ValidationContext) = - let fragmentDefinitions = ctx.FragmentDefinitions |> List.map (fun x -> x.Definition) + let fragmentDefinitions = ctx.FragmentDefinitions |> List.map _.Definition ctx.Document.Definitions |> ValidationResult.collect (fun def -> let path = def.Name |> ValueOption.map box |> ValueOption.toList @@ -1194,16 +1195,16 @@ module Ast = match selection with | Field field -> let path = box field.AliasOrName :: path - let fieldDirectives = [ path, field.Directives |> List.map (fun x -> x.Name) ] + let fieldDirectives = [ path, field.Directives |> List.map _.Name ] let selectionSetDirectives = field.SelectionSet |> List.collect (getDirectiveNamesInSelection path) fieldDirectives |> List.append selectionSetDirectives | InlineFragment frag -> getDirectiveNamesInDefinition path (FragmentDefinition frag) - | FragmentSpread spread -> [ path, spread.Directives |> List.map (fun x -> x.Name) ] + | FragmentSpread spread -> [ path, spread.Directives |> List.map _.Name ] and private getDirectiveNamesInDefinition (path : FieldPath) (frag : Definition) : (FieldPath * string list) list = - let fragDirectives = [ path, frag.Directives |> List.map (fun x -> x.Name) ] + let fragDirectives = [ path, frag.Directives |> List.map _.Name ] let selectionSetDirectives = frag.SelectionSet |> List.collect (getDirectiveNamesInSelection path) @@ -1216,14 +1217,14 @@ module Ast = match def.Name with | ValueSome name -> [ box name ] | ValueNone -> [] - let defDirectives = path, def.Directives |> List.map (fun x -> x.Name) + let defDirectives = path, def.Directives |> List.map _.Name let selectionSetDirectives = def.Definition.SelectionSet |> List.collect (getDirectiveNamesInSelection path) defDirectives :: selectionSetDirectives) |> ValidationResult.collect (fun (path, directives) -> directives - |> List.countBy id + |> Seq.countBy id |> ValidationResult.collect (fun (name, count) -> if count <= 1 then Success @@ -1324,8 +1325,8 @@ module Ast = let path = def.Name |> ValueOption.map box |> ValueOption.toList let varNames = def.VariableDefinitions - |> List.map (fun x -> x.VariableName) - |> Set.ofList + |> Seq.map _.VariableName + |> Set.ofSeq def.SelectionSet |> ValidationResult.collect (checkVariablesDefinedInSelection fragmentDefinitions varNames path) | _ -> Success) @@ -1338,7 +1339,7 @@ module Ast = | ObjectValue obj -> go (Map.toList obj |> List.map snd) | ListValue xs -> go xs | _ -> false) - go (args |> List.map (fun x -> x.Value)) + go (args |> List.map _.Value) let rec private variableIsUsedInFragmentSpread (name : string) From 5612b7ede70d4cd0575079c29c4fa321ede81285 Mon Sep 17 00:00:00 2001 From: Andrii Chebukin Date: Mon, 18 Aug 2025 00:48:40 +0400 Subject: [PATCH 2/2] Migrated to underscore property access lambda syntax --- samples/relay-book-store/Schema.fs | 4 ++-- .../GraphQLProvider.DesignTime.fs | 4 ++-- .../ProvidedTypesHelper.fs | 6 +++--- src/FSharp.Data.GraphQL.Client/BaseTypes.fs | 2 +- src/FSharp.Data.GraphQL.Client/Extensions.fs | 2 +- src/FSharp.Data.GraphQL.Server/Execution.fs | 2 +- src/FSharp.Data.GraphQL.Server/Executor.fs | 2 +- src/FSharp.Data.GraphQL.Server/Values.fs | 2 +- .../SwapiRemoteProviderTests.fs | 2 +- tests/FSharp.Data.GraphQL.Tests/DeferredTests.fs | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/samples/relay-book-store/Schema.fs b/samples/relay-book-store/Schema.fs index f5ba3fa7..7f99e8e9 100644 --- a/samples/relay-book-store/Schema.fs +++ b/samples/relay-book-store/Schema.fs @@ -159,14 +159,14 @@ let booksField = let startCursor = async { let! edges = edges - return edges |> Seq.tryHead |> Option.map (fun x -> x.Cursor) + return edges |> Seq.tryHead |> Option.map _.Cursor } // The cursor of the last edge let endCursor = async { let! edges = edges - return edges |> Seq.tryLast |> Option.map (fun x -> x.Cursor) + return edges |> Seq.tryLast |> Option.map _.Cursor } { diff --git a/src/FSharp.Data.GraphQL.Client.DesignTime/GraphQLProvider.DesignTime.fs b/src/FSharp.Data.GraphQL.Client.DesignTime/GraphQLProvider.DesignTime.fs index cfb7c410..d8888005 100644 --- a/src/FSharp.Data.GraphQL.Client.DesignTime/GraphQLProvider.DesignTime.fs +++ b/src/FSharp.Data.GraphQL.Client.DesignTime/GraphQLProvider.DesignTime.fs @@ -26,8 +26,8 @@ type GraphQLTypeProvider (config) as this = if args.Name.Contains("FSharp.Data.GraphQL") then printfn "ResolveAssembly: %s" args.Name config.ReferencedAssemblies - |> Array.filter(fun x -> x.Contains("FSharp.Data")) - |> Array.iter (fun x -> printfn "%s" x) + |> Array.filter _.Contains("FSharp.Data") + |> Array.iter (fun x -> printfn "%s" x) base.ResolveAssembly args [] diff --git a/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs b/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs index f94f327b..59ee6d98 100644 --- a/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs +++ b/src/FSharp.Data.GraphQL.Client.DesignTime/ProvidedTypesHelper.fs @@ -184,7 +184,7 @@ module internal ProvidedRecord = |> List.partition (fun (_, t) -> isOption t) if explicitOptionalParameters then let constructorProperties = requiredProperties @ optionalProperties - let propertyNames = constructorProperties |> List.map (fst >> (fun x -> x.FirstCharUpper())) + let propertyNames = constructorProperties |> List.map (fst >> _.FirstCharUpper()) let constructorPropertyTypes = constructorProperties |> List.map snd let invoker (args : Expr list) = let properties = @@ -208,7 +208,7 @@ module internal ProvidedRecord = List.combinations optionalProperties |> List.map (fun (optionalProperties, nullValuedProperties) -> let constructorProperties = requiredProperties @ optionalProperties - let propertyNames = (constructorProperties @ nullValuedProperties) |> List.map (fst >> (fun x -> x.FirstCharUpper())) + let propertyNames = (constructorProperties @ nullValuedProperties) |> List.map (fst >> _.FirstCharUpper()) let constructorPropertyTypes = constructorProperties |> List.map snd let nullValuedPropertyTypes = nullValuedProperties |> List.map snd let invoker (args : Expr list) = @@ -554,7 +554,7 @@ module internal Provider = | TypeField _ -> Some x | FragmentField f when f.TypeCondition = tref.Name.Value -> Some x | _ -> None) - |> List.distinctBy (fun x -> x.AliasOrName) + |> List.distinctBy _.AliasOrName |> List.map (getPropertyMetadata tref.Name.Value) let baseType = let metadata : ProvidedTypeMetadata = { Name = tref.Name.Value; Description = tref.Description } diff --git a/src/FSharp.Data.GraphQL.Client/BaseTypes.fs b/src/FSharp.Data.GraphQL.Client/BaseTypes.fs index 141d1221..e1f4034f 100644 --- a/src/FSharp.Data.GraphQL.Client/BaseTypes.fs +++ b/src/FSharp.Data.GraphQL.Client/BaseTypes.fs @@ -104,7 +104,7 @@ type RecordBase (name : string, properties : RecordProperty seq) = let properties = if not (isNull properties) - then properties |> Seq.sortBy (fun x -> x.Name) |> List.ofSeq + then properties |> Seq.sortBy _.Name |> List.ofSeq else [] /// Gets the name of this provided record type. diff --git a/src/FSharp.Data.GraphQL.Client/Extensions.fs b/src/FSharp.Data.GraphQL.Client/Extensions.fs index 5c3cf935..ed1a3adb 100644 --- a/src/FSharp.Data.GraphQL.Client/Extensions.fs +++ b/src/FSharp.Data.GraphQL.Client/Extensions.fs @@ -23,7 +23,7 @@ module internal Extensions = member this.MD5Hash() = Encoding.UTF8.GetBytes(this) |> MD5.Create().ComputeHash - |> Array.map (fun x -> x.ToString("x2")) + |> Array.map _.ToString("x2") |> Array.reduce (+) /// Basic operations on lists. diff --git a/src/FSharp.Data.GraphQL.Server/Execution.fs b/src/FSharp.Data.GraphQL.Server/Execution.fs index 737ed4b5..a41987f1 100644 --- a/src/FSharp.Data.GraphQL.Server/Execution.fs +++ b/src/FSharp.Data.GraphQL.Server/Execution.fs @@ -336,7 +336,7 @@ and private live (inputContext : InputExecutionContextProvider) (ctx : ResolveFi |> Observable.mergeInner let provider = ctx.Schema.LiveFieldSubscriptionProvider - let filter = provider.TryFind typeName name |> Option.map (fun x -> x.Filter) + let filter = provider.TryFind typeName name |> Option.map _.Filter let updates = match filter with | Some filterFn -> provider.Add (filterFn parent) typeName name |> Observable.bind resolveUpdate diff --git a/src/FSharp.Data.GraphQL.Server/Executor.fs b/src/FSharp.Data.GraphQL.Server/Executor.fs index 0d296327..85089c99 100644 --- a/src/FSharp.Data.GraphQL.Server/Executor.fs +++ b/src/FSharp.Data.GraphQL.Server/Executor.fs @@ -170,7 +170,7 @@ type Executor<'Root>(schema: ISchema<'Root>, middlewares : IExecutorMiddleware s Metadata = meta Operation = operation DocumentId = documentId } - return runMiddlewares (fun x -> x.PlanOperation) planningCtx planOperation + return runMiddlewares _.PlanOperation planningCtx planOperation | None -> return! Error <| [ GQLProblemDetails.CreateWithKind ( "No operation with specified name has been found for provided document", ErrorKind.Validation diff --git a/src/FSharp.Data.GraphQL.Server/Values.fs b/src/FSharp.Data.GraphQL.Server/Values.fs index 7d315354..e7fd7e5d 100644 --- a/src/FSharp.Data.GraphQL.Server/Values.fs +++ b/src/FSharp.Data.GraphQL.Server/Values.fs @@ -105,7 +105,7 @@ let rec internal compileByType | InputCustom customDef -> fun inputContext value variables -> customDef.CoerceInput inputContext (InlineConstant value) variables | InputObject objDef -> let objType = objDef.Type - let ctor = ReflectionHelper.matchConstructor objType (objDef.Fields |> Array.map (fun x -> x.Name)) + let ctor = ReflectionHelper.matchConstructor objType (objDef.Fields |> Array.map _.Name) let parametersMap = let typeMismatchParameters = HashSet () diff --git a/tests/FSharp.Data.GraphQL.IntegrationTests/SwapiRemoteProviderTests.fs b/tests/FSharp.Data.GraphQL.IntegrationTests/SwapiRemoteProviderTests.fs index 1cf9b399..dc73b38d 100644 --- a/tests/FSharp.Data.GraphQL.IntegrationTests/SwapiRemoteProviderTests.fs +++ b/tests/FSharp.Data.GraphQL.IntegrationTests/SwapiRemoteProviderTests.fs @@ -174,7 +174,7 @@ module FileOperation = Operation.Types.HeroFields.FriendsFields.EdgesFields.NodeFields.Human(name = "Leia Organa", homePlanet = "Alderaan") Operation.Types.HeroFields.FriendsFields.EdgesFields.NodeFields.Droid(name = "C-3PO", primaryFunction = "Protocol") Operation.Types.HeroFields.FriendsFields.EdgesFields.NodeFields.Droid(name = "R2-D2", primaryFunction = "Astromech") |] - let friends = result.Data.Value.Hero.Value.Friends.Edges |> Array.map (fun x -> x.Node) + let friends = result.Data.Value.Hero.Value.Friends.Edges |> Array.map _.Node friends |> equals expectedFriends result.Data.Value.Hero.Value.HomePlanet |> equals (Some "Tatooine") let actual = normalize <| sprintf "%A" result.Data diff --git a/tests/FSharp.Data.GraphQL.Tests/DeferredTests.fs b/tests/FSharp.Data.GraphQL.Tests/DeferredTests.fs index 3ce28c0d..a687e5e6 100644 --- a/tests/FSharp.Data.GraphQL.Tests/DeferredTests.fs +++ b/tests/FSharp.Data.GraphQL.Tests/DeferredTests.fs @@ -247,7 +247,7 @@ let sub = { FieldName = "live" TypeName = "Data" Filter = (fun (x : TestSubject) (y : TestSubject) -> x.id = y.id) - Project = (fun x -> x.live) } + Project = _.live } schemaConfig.LiveFieldSubscriptionProvider.Register sub