Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
28 changes: 28 additions & 0 deletions src/SwaggerProvider.DesignTime/Provider.OpenApiClient.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ open System.Reflection
open Microsoft.OpenApi.Reader
open ProviderImplementation.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Reflection
open Swagger
open SwaggerProvider.Internal
open SwaggerProvider.Internal.v3.Compilers
Expand All @@ -28,6 +30,14 @@ type public OpenApiClientTypeProvider(cfg: TypeProviderConfig) as this =
// check we contain a copy of runtime files, and are not referencing the runtime DLL
do assert (typeof<ProvidedApiClientBase>.Assembly.GetName().Name = asm.GetName().Name)

let buildStringListExpr(items: string list) : Expr =
let cases = FSharpType.GetUnionCases typeof<string list>
let nilCase = cases |> Array.find(fun c -> c.Name = "Empty")
let consCase = cases |> Array.find(fun c -> c.Name = "Cons")
let nil = Expr.NewUnionCase(nilCase, [])

List.foldBack (fun (s: string) acc -> Expr.NewUnionCase(consCase, [ Expr.Value(s, typeof<string>); acc ])) items nil

let myParamType =
let t =
ProvidedTypeDefinition(asm, ns, "OpenApiClientProvider", Some typeof<obj>, isErased = false)
Expand Down Expand Up @@ -103,6 +113,11 @@ type public OpenApiClientTypeProvider(cfg: TypeProviderConfig) as this =
|> Seq.map(fun e -> $"%s{e.Message} @ %s{e.Pointer}")
|> String.concat "\n")

let parseErrors =
diagnostic.Errors
|> Seq.map(fun e -> $"%s{e.Message} @ %s{e.Pointer}")
|> Seq.toList

let defCompiler = DefinitionCompiler(schema, preferNullable)

let opCompiler =
Expand All @@ -118,6 +133,19 @@ type public OpenApiClientTypeProvider(cfg: TypeProviderConfig) as this =

ty.AddXmlDoc("OpenAPI Provider for " + schemaPathRaw)
ty.AddMembers tys

let errProp =
ProvidedProperty(
"SchemaReaderErrors",
typeof<string list>,
isStatic = true,
getterCode = fun _ -> buildStringListExpr parseErrors
)

errProp.AddXmlDoc
"List of OpenAPI parse errors tolerated by this provider instance. Non-empty only when IgnoreParseErrors=true and the schema has validation issues."

ty.AddMember errProp
tempAsm.AddTypes [ ty ]

ty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<Compile Include="v3\Swagger.I0219.Tests.fs" />
<Compile Include="v3\Swagger.I0279.Tests.fs" />
<Compile Include="v3\Swagger.NullableDate.Tests.fs" />
<Compile Include="v3\Swagger.SchemaReaderErrors.Tests.fs" />
<Compile Include="v3\Swashbuckle.ReturnControllers.Tests.fs" />
<Compile Include="v3\Swashbuckle.ReturnTextControllers.Tests.fs" />
<Compile Include="v3\Swashbuckle.UpdateControllers.Tests.fs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Swagger.SchemaReaderErrors.Tests

open SwaggerProvider
open Xunit
open FsUnitTyped

[<Literal>]
let ValidSchema = __SOURCE_DIRECTORY__ + "/../Schemas/v3/petstore.yaml"

[<Literal>]
let SchemaWithErrors =
__SOURCE_DIRECTORY__
+ "/../Schemas/v3/nullable-parameter-issue261.json"

type ValidApi = OpenApiClientProvider<ValidSchema>

type ApiWithErrors = OpenApiClientProvider<SchemaWithErrors, IgnoreParseErrors=true>

[<Fact>]
let ``SchemaReaderErrors is empty for a valid schema``() =
ValidApi.SchemaReaderErrors |> shouldEqual []

[<Fact>]
let ``SchemaReaderErrors is non-empty when IgnoreParseErrors=true and schema has validation errors``() =
ApiWithErrors.SchemaReaderErrors |> List.isEmpty |> shouldEqual false

[<Fact>]
let ``SchemaReaderErrors entries contain message and pointer``() =
let errors = ApiWithErrors.SchemaReaderErrors
errors |> List.isEmpty |> shouldEqual false

for entry in errors do
entry.Contains(" @ ") |> shouldEqual true
Loading