Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/SwaggerProvider.DesignTime/Provider.OpenApiClient.fs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ type public OpenApiClientTypeProvider(cfg: TypeProviderConfig) as this =
|> Seq.toList

let useDateOnly = cfg.SystemRuntimeAssemblyVersion.Major >= 6

let defCompiler = DefinitionCompiler(schema, preferNullable, useDateOnly)

Comment thread
sergey-tihon marked this conversation as resolved.
let opCompiler =
Expand Down
2 changes: 2 additions & 0 deletions src/SwaggerProvider.DesignTime/v3/DefinitionCompiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ type DefinitionCompiler(schema: OpenApiDocument, provideNullable, useDateOnly: b
typedefof<Option<obj>>

ProvidedTypeBuilder.MakeGenericType(baseGenTy, [ tyType ])
else if tyType = typeof<string> then
ProvidedTypeBuilder.MakeGenericType(typedefof<Option<obj>>, [ tyType ])
Comment thread
sergey-tihon marked this conversation as resolved.
Outdated
else
tyType

Expand Down
16 changes: 8 additions & 8 deletions tests/SwaggerProvider.Tests/v3/Schema.TypeMappingTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,15 @@ let ``optional Guid maps to Option<Guid>``() =

ty |> shouldEqual(typedefof<Option<_>>.MakeGenericType(typeof<Guid>))

// ── Optional reference types are NOT wrapped (they are already nullable) ─────
// ── Optional string is wrapped in Option<string> ─────────────────────────────

[<Fact>]
let ``optional string is not wrapped in Option``() =
let ``optional string maps to Option<string>``() =
let ty = compilePropertyType " type: string\n" false

// string is a reference type — not wrapped in Option<T> even when non-required
ty |> shouldEqual typeof<string>
// plain string fields are wrapped in Option<string> when non-required
ty
|> shouldEqual(typedefof<Option<_>>.MakeGenericType(typeof<string>))
Comment thread
sergey-tihon marked this conversation as resolved.
Outdated

[<Fact>]
let ``optional byte array is not wrapped in Option``() =
Expand Down Expand Up @@ -403,8 +404,7 @@ let ``PreferNullable: required integer is not wrapped (Nullable only for optiona
ty |> shouldEqual typeof<int32>

[<Fact>]
let ``PreferNullable: optional string is not wrapped (reference type)``() =
// Reference types like string are not wrapped in Nullable<T> since they are
// already nullable by nature — same behaviour as Option mode.
let ``PreferNullable: optional string maps to Option<string>``() =
// Strings are always wrapped in Option<string> when non-required, even with PreferNullable.
let ty = compilePropertyTypeWith true " type: string\n" false
ty |> shouldEqual typeof<string>
ty |> shouldEqual typeof<string option>
Comment thread
sergey-tihon marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ let ``v2 petstore Pet type has correct property types``() =
idProp.PropertyType |> shouldEqual typeof<int64>
// required string
nameProp.PropertyType |> shouldEqual typeof<string>
// optional string — string is a reference type, not wrapped in Option
tagProp.PropertyType |> shouldEqual typeof<string>
// optional string — now wrapped in Option<string>
tagProp.PropertyType |> shouldEqual typeof<string option>
Comment thread
sergey-tihon marked this conversation as resolved.

[<Fact>]
let ``v2 petstore schema generates API client types with operations``() =
Expand Down
Loading