From b504e781b961c986ee4e07075104926246c3c4b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 22:16:25 +0000 Subject: [PATCH 1/3] Initial plan From 6ee766f3f67b37349f7b90aea645b8b3f2a6d3ab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 22:24:32 +0000 Subject: [PATCH 2/3] fix: switch from overloads to optional CancellationToken parameter in generated methods Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/4498d505-289e-4053-b797-faf89db707dd --- .../v3/OperationCompiler.fs | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs b/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs index 33b8705..12aed18 100644 --- a/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs +++ b/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs @@ -60,7 +60,7 @@ type PayloadType = /// Object for compiling operations. type OperationCompiler(schema: OpenApiDocument, defCompiler: DefinitionCompiler, ignoreControllerPrefix, ignoreOperationId, asAsync: bool) = - let compileOperation (providedMethodName: string) (apiCall: ApiCall) (includeCancellationToken: bool) = + let compileOperation (providedMethodName: string) (apiCall: ApiCall) = let path, pathItem, opTy = apiCall let operation = pathItem.Operations[opTy] @@ -179,13 +179,10 @@ type OperationCompiler(schema: OpenApiDocument, defCompiler: DefinitionCompiler, |> List.rev let parameters = - if includeCancellationToken then - let ctParam = - ProvidedParameter("cancellationToken", typeof) + let ctParam = + ProvidedParameter("cancellationToken", typeof, optionalValue = (null: obj)) - providedParameters @ [ ctParam ] - else - providedParameters + providedParameters @ [ ctParam ] payloadTy.ToMediaType(), parameters @@ -273,18 +270,15 @@ type OperationCompiler(schema: OpenApiDocument, defCompiler: DefinitionCompiler, // Locates parameters matching the arguments let mutable payloadExp = None - // When the CancellationToken overload is generated, CancellationToken is always appended last. + // CancellationToken is always appended last as an optional parameter. // Extract it by position to avoid name-collision issues and invalid Expr.Coerce // on a struct type (which generates an invalid castclass IL instruction). let apiArgs, ct = let allArgs = List.tail args // skip `this` - if includeCancellationToken then - match List.rev allArgs with - | ctArg :: revApiArgs -> List.rev revApiArgs, Expr.Cast(ctArg) - | [] -> failwith "Expected CancellationToken argument but argument list was empty" - else - allArgs, <@ Threading.CancellationToken.None @> + match List.rev allArgs with + | ctArg :: revApiArgs -> List.rev revApiArgs, Expr.Cast(ctArg) + | [] -> failwith "Expected CancellationToken argument but argument list was empty" let parameters = apiArgs @@ -622,10 +616,5 @@ type OperationCompiler(schema: OpenApiDocument, defCompiler: DefinitionCompiler, let name = OperationCompiler.GetMethodNameCandidate op skipLength ignoreOperationId let uniqueName = methodNameScope.MakeUnique name - // Generate two overloads: one without CancellationToken (backward compatible) - // and one with an explicit CancellationToken parameter. - // We cannot use an optional struct parameter with a default value because - // struct values (e.g., CancellationToken.None) cannot be stored in DefaultParameterValue - // custom attributes. - [ compileOperation uniqueName op false; compileOperation uniqueName op true ]) + [ compileOperation uniqueName op ]) |> ty.AddMembers) From f6fa43f93d7b55b01de5cda06936155851131241 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 22:26:27 +0000 Subject: [PATCH 3/3] fix: add comment explaining null encoding for optional CancellationToken parameter Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/4498d505-289e-4053-b797-faf89db707dd --- src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs b/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs index 12aed18..cca5e24 100644 --- a/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs +++ b/src/SwaggerProvider.DesignTime/v3/OperationCompiler.fs @@ -179,6 +179,10 @@ type OperationCompiler(schema: OpenApiDocument, defCompiler: DefinitionCompiler, |> List.rev let parameters = + // Passing null as optionalValue encodes default(CancellationToken) in CLI metadata, + // which is the standard way to represent `ct = default` for struct parameters + // (equivalent to CancellationToken.None). A boxed struct value cannot be used + // here because CancellationToken is not a valid custom attribute argument type. let ctParam = ProvidedParameter("cancellationToken", typeof, optionalValue = (null: obj))