Skip to content

Commit 0859f3c

Browse files
committed
Merge branch 'swagger-inline-response-schemas' into swagger-default-responses
2 parents 044835c + a196b18 commit 0859f3c

3 files changed

Lines changed: 43 additions & 23 deletions

File tree

ConsumePlugin/GeneratedSwaggerAnonymousTypes.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ type Type1 =
2323
Name : string option
2424
}
2525

26+
[<JsonParse true ; JsonSerialize true>]
27+
type Type2147483647 =
28+
{
29+
[<System.Text.Json.Serialization.JsonExtensionData>]
30+
AdditionalProperties : System.Collections.Generic.Dictionary<string, System.Text.Json.Nodes.JsonNode>
31+
[<System.Text.Json.Serialization.JsonPropertyName "wouldOverflowASeededCounter">]
32+
WouldOverflowASeededCounter : string option
33+
}
34+
2635
[<JsonParse true ; JsonSerialize true>]
2736
type Type2 =
2837
{

ConsumePlugin/swagger-anonymous-types.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@
5050
"type": "string"
5151
}
5252
}
53+
},
54+
"Type2147483647": {
55+
"type": "object",
56+
"properties": {
57+
"wouldOverflowASeededCounter": {
58+
"type": "string"
59+
}
60+
}
5361
}
5462
},
5563
"responses": {}

WoofWare.Myriad.Plugins/SwaggerClientGenerator.fs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ module internal SwaggerClientGenerator =
6969
| SwaggerV2.Definition.File -> SynType.createLongIdent' [ "System" ; "IO" ; "Stream" ] |> Some
7070

7171
/// Returns None if we lacked the information required to do this.
72+
/// nextAnonymousTypeName must return a fresh unused type name on each call.
7273
/// bigCache is a map of e.g. {"securityDefinition": {Defn : F# type}}.
7374
let rec defnToType
74-
(anonymousTypeCount : int ref)
75+
(nextAnonymousTypeName : unit -> string)
7576
(handlesMap : Dictionary<string, TypeEntry>)
7677
(bigCache : Dictionary<string, Dictionary<SwaggerV2.Definition, TypeEntry>>)
7778
(thisKey : string)
@@ -154,7 +155,7 @@ module internal SwaggerClientGenerator =
154155
|> Some
155156
| None ->
156157

157-
let defn' = defnToType anonymousTypeCount handlesMap bigCache thisKey None defn
158+
let defn' = defnToType nextAnonymousTypeName handlesMap bigCache thisKey None defn
158159

159160
match defn' with
160161
| None -> None
@@ -200,7 +201,7 @@ module internal SwaggerClientGenerator =
200201
|> Some
201202
| Some SwaggerV2.AdditionalProperties.Never -> Some []
202203
| Some (SwaggerV2.AdditionalProperties.Constrained defn) ->
203-
let defn' = defnToType anonymousTypeCount handlesMap bigCache thisKey None defn
204+
let defn' = defnToType nextAnonymousTypeName handlesMap bigCache thisKey None defn
204205

205206
match defn' with
206207
| None -> None
@@ -234,7 +235,7 @@ module internal SwaggerClientGenerator =
234235

235236
let fSharpTypeName =
236237
match typeName with
237-
| None -> $"Type%i{Interlocked.Increment anonymousTypeCount}"
238+
| None -> nextAnonymousTypeName ()
238239
| Some typeName -> typeName
239240

240241
let properties = additionalProperties @ namedProperties
@@ -278,7 +279,8 @@ module internal SwaggerClientGenerator =
278279
defn |> Some
279280

280281
| SwaggerV2.Definition.Array elt ->
281-
let child = defnToType anonymousTypeCount handlesMap bigCache thisKey None elt.Items
282+
let child =
283+
defnToType nextAnonymousTypeName handlesMap bigCache thisKey None elt.Items
282284

283285
match child with
284286
| None -> None
@@ -540,35 +542,36 @@ module internal SwaggerV2Generator =
540542
(0, bigCache) ||> Seq.fold (fun count (KeyValue (_, v)) -> count + v.Count)
541543

542544
let byHandle = Dictionary ()
543-
let anonymousTypeCount = ref 0
544545

545546
// A spec is free to define types whose (sanitised) names look like the
546-
// "Type{N}" names we invent for anonymous inline schemas; start counting
547-
// past any such name so we never collide with them.
548-
let namedTypes =
549-
seq {
550-
for KeyValue (k, _) in contents.Definitions do
551-
yield k
552-
553-
for KeyValue (k, _) in contents.Responses do
554-
yield k
555-
}
547+
// "Type{N}" names we invent for anonymous inline schemas (including
548+
// pathological ones like "Type2147483647", which would overflow a
549+
// seeded counter); skip over any name that's already taken.
550+
let takenNames = HashSet<string> ()
551+
552+
for KeyValue (k, _) in contents.Definitions do
553+
takenNames.Add (Ident.createSanitisedTypeName k).idText |> ignore<bool>
554+
555+
for KeyValue (k, _) in contents.Responses do
556+
takenNames.Add (Ident.createSanitisedTypeName k).idText |> ignore<bool>
557+
558+
let anonymousTypeCount = ref 0
559+
560+
let nextAnonymousTypeName () : string =
561+
let mutable candidate = $"Type%i{Interlocked.Increment anonymousTypeCount}"
556562

557-
for name in namedTypes do
558-
let name = (Ident.createSanitisedTypeName name).idText
563+
while takenNames.Contains candidate do
564+
candidate <- $"Type%i{Interlocked.Increment anonymousTypeCount}"
559565

560-
if name.StartsWith ("Type", System.StringComparison.Ordinal) then
561-
match System.Int32.TryParse (name.Substring "Type".Length) with
562-
| true, n -> anonymousTypeCount.Value <- max anonymousTypeCount.Value n
563-
| false, _ -> ()
566+
candidate
564567

565568
let rec go (contents : ((string option * SwaggerV2.Definition) * string) list) =
566569
let lastRound = countAll ()
567570

568571
contents
569572
|> List.filter (fun ((name, defn), defnClass) ->
570573
let doIt =
571-
SwaggerClientGenerator.defnToType anonymousTypeCount byHandle bigCache defnClass name defn
574+
SwaggerClientGenerator.defnToType nextAnonymousTypeName byHandle bigCache defnClass name defn
572575

573576
match doIt with
574577
| None -> true

0 commit comments

Comments
 (0)