mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-17 18:08:40 +00:00
Compare commits
3 Commits
WoofWare.M
...
WoofWare.M
Author | SHA1 | Date | |
---|---|---|---|
|
7b14e52e9d | ||
|
8e47f39efc | ||
|
6942ba42b9 |
@@ -1,5 +1,14 @@
|
|||||||
Notable changes are recorded here.
|
Notable changes are recorded here.
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 2.1.33
|
||||||
|
|
||||||
|
`JsonParse` can now deserialize the discriminated unions which `JsonSerialize` wrote out.
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 2.1.32, WoofWare.Myriad.Plugins.Attributes 3.1.4
|
||||||
|
|
||||||
|
`JsonSerialize` can now serialize many discriminated unions.
|
||||||
|
(This operation is inherently opinionated, because JSON does not model discriminated unions.)
|
||||||
|
|
||||||
# WoofWare.Myriad.Plugins 2.1.20, WoofWare.Myriad.Plugins.Attributes 3.0.1
|
# WoofWare.Myriad.Plugins 2.1.20, WoofWare.Myriad.Plugins.Attributes 3.0.1
|
||||||
|
|
||||||
We now bundle copies of the RestEase attributes in `WoofWare.Myriad.Plugins.Attributes`, in case you don't want to take a dependency on RestEase.
|
We now bundle copies of the RestEase attributes in `WoofWare.Myriad.Plugins.Attributes`, in case you don't want to take a dependency on RestEase.
|
||||||
|
@@ -8,8 +8,7 @@
|
|||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the InnerType type
|
/// Module containing JSON parsing methods for the InnerType type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module InnerType =
|
module InnerType =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType =
|
||||||
@@ -31,8 +30,7 @@ module InnerType =
|
|||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JsonRecordType type
|
/// Module containing JSON parsing methods for the JsonRecordType type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JsonRecordType =
|
module JsonRecordType =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType =
|
||||||
|
@@ -195,7 +195,7 @@ type internal TypeWithInterfaceMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : TypeWithInterfaceMock =
|
static member Empty : TypeWithInterfaceMock =
|
||||||
{
|
{
|
||||||
Dispose = (fun _ -> ())
|
Dispose = (fun () -> ())
|
||||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||||
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||||
}
|
}
|
||||||
|
@@ -41,8 +41,7 @@ module MemberJsonSerializeExtension =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymOpeningHours type
|
/// Module containing JSON parsing methods for the GymOpeningHours type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymOpeningHours =
|
module GymOpeningHours =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymOpeningHours =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymOpeningHours =
|
||||||
@@ -78,8 +77,7 @@ module GymOpeningHours =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymAccessOptions type
|
/// Module containing JSON parsing methods for the GymAccessOptions type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymAccessOptions =
|
module GymAccessOptions =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAccessOptions =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAccessOptions =
|
||||||
@@ -114,8 +112,7 @@ module GymAccessOptions =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymLocation type
|
/// Module containing JSON parsing methods for the GymLocation type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymLocation =
|
module GymLocation =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymLocation =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymLocation =
|
||||||
@@ -192,8 +189,7 @@ module GymLocation =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymAddress type
|
/// Module containing JSON parsing methods for the GymAddress type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymAddress =
|
module GymAddress =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAddress =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAddress =
|
||||||
@@ -259,8 +255,7 @@ module GymAddress =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the Gym type
|
/// Module containing JSON parsing methods for the Gym type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module Gym =
|
module Gym =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Gym =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Gym =
|
||||||
@@ -620,8 +615,7 @@ module MemberJsonParseExtension =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymAttendance type
|
/// Module containing JSON parsing methods for the GymAttendance type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymAttendance =
|
module GymAttendance =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAttendance =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAttendance =
|
||||||
@@ -743,8 +737,7 @@ module GymAttendance =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the MemberActivityDto type
|
/// Module containing JSON parsing methods for the MemberActivityDto type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module MemberActivityDto =
|
module MemberActivityDto =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : MemberActivityDto =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : MemberActivityDto =
|
||||||
@@ -832,8 +825,7 @@ module MemberActivityDto =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the SessionsAggregate type
|
/// Module containing JSON parsing methods for the SessionsAggregate type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module SessionsAggregate =
|
module SessionsAggregate =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
|
||||||
@@ -881,8 +873,7 @@ module SessionsAggregate =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the VisitGym type
|
/// Module containing JSON parsing methods for the VisitGym type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module VisitGym =
|
module VisitGym =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
|
||||||
@@ -930,8 +921,7 @@ module VisitGym =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the Visit type
|
/// Module containing JSON parsing methods for the Visit type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module Visit =
|
module Visit =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
|
||||||
@@ -993,8 +983,7 @@ module Visit =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the SessionsSummary type
|
/// Module containing JSON parsing methods for the SessionsSummary type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module SessionsSummary =
|
module SessionsSummary =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
|
||||||
@@ -1029,8 +1018,7 @@ module SessionsSummary =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the Sessions type
|
/// Module containing JSON parsing methods for the Sessions type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module Sessions =
|
module Sessions =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
|
||||||
@@ -1066,8 +1054,7 @@ module Sessions =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the UriThing type
|
/// Module containing JSON parsing methods for the UriThing type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module UriThing =
|
module UriThing =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing =
|
||||||
|
@@ -17,8 +17,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module PureGymApi =
|
module PureGymApi =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IPureGymApi =
|
let make (client : System.Net.Http.HttpClient) : IPureGymApi =
|
||||||
@@ -1055,8 +1054,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module internal ApiWithoutBaseAddress =
|
module internal ApiWithoutBaseAddress =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IApiWithoutBaseAddress =
|
let make (client : System.Net.Http.HttpClient) : IApiWithoutBaseAddress =
|
||||||
@@ -1107,8 +1105,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module ApiWithBasePath =
|
module ApiWithBasePath =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IApiWithBasePath =
|
let make (client : System.Net.Http.HttpClient) : IApiWithBasePath =
|
||||||
@@ -1159,8 +1156,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module ApiWithBasePathAndAddress =
|
module ApiWithBasePathAndAddress =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IApiWithBasePathAndAddress =
|
let make (client : System.Net.Http.HttpClient) : IApiWithBasePathAndAddress =
|
||||||
@@ -1205,8 +1201,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module ApiWithHeaders =
|
module ApiWithHeaders =
|
||||||
/// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties.
|
/// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties.
|
||||||
let make
|
let make
|
||||||
@@ -1268,8 +1263,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module ApiWithHeaders2 =
|
module ApiWithHeaders2 =
|
||||||
/// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties.
|
/// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties.
|
||||||
let make
|
let make
|
||||||
|
@@ -8,8 +8,7 @@
|
|||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JwtVaultAuthResponse type
|
/// Module containing JSON parsing methods for the JwtVaultAuthResponse type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JwtVaultAuthResponse =
|
module JwtVaultAuthResponse =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultAuthResponse =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultAuthResponse =
|
||||||
@@ -164,8 +163,7 @@ module JwtVaultAuthResponse =
|
|||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JwtVaultResponse type
|
/// Module containing JSON parsing methods for the JwtVaultResponse type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JwtVaultResponse =
|
module JwtVaultResponse =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultResponse =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultResponse =
|
||||||
@@ -239,8 +237,7 @@ module JwtVaultResponse =
|
|||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JwtSecretResponse type
|
/// Module containing JSON parsing methods for the JwtSecretResponse type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JwtSecretResponse =
|
module JwtSecretResponse =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtSecretResponse =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtSecretResponse =
|
||||||
@@ -455,8 +452,7 @@ open System.Threading.Tasks
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module VaultClient =
|
module VaultClient =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IVaultClient =
|
let make (client : System.Net.Http.HttpClient) : IVaultClient =
|
||||||
@@ -553,8 +549,7 @@ open System.Threading.Tasks
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module VaultClientNonExtensionMethod =
|
module VaultClientNonExtensionMethod =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IVaultClientNonExtensionMethod =
|
let make (client : System.Net.Http.HttpClient) : IVaultClientNonExtensionMethod =
|
||||||
|
@@ -193,12 +193,13 @@ module TestJsonSerde =
|
|||||||
|
|
||||||
let decompose = FSharpValue.PreComputeUnionTagReader typeof<FirstDu>
|
let decompose = FSharpValue.PreComputeUnionTagReader typeof<FirstDu>
|
||||||
|
|
||||||
Gen.listOf duGen
|
let mutable i = 0
|
||||||
|> Gen.eval 100 (StdGen.StdGen (rand.Next (), rand.Next ()))
|
|
||||||
|> List.iter (fun du ->
|
while i < 10_000 && Array.exists (fun i -> i = 0) counts do
|
||||||
|
let du = Gen.eval 10 (StdGen.StdGen (rand.Next (), rand.Next ())) duGen
|
||||||
let tag = decompose du
|
let tag = decompose du
|
||||||
counts.[tag] <- counts.[tag] + 1
|
counts.[tag] <- counts.[tag] + 1
|
||||||
)
|
i <- i + 1
|
||||||
|
|
||||||
for i in counts do
|
for i in counts do
|
||||||
i |> shouldBeGreaterThan 0
|
i |> shouldBeGreaterThan 0
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
open Fantomas.FCS.Xml
|
open Fantomas.FCS.Xml
|
||||||
open Myriad.Core.AstExtensions
|
|
||||||
|
|
||||||
type internal ParameterInfo =
|
type internal ParameterInfo =
|
||||||
{
|
{
|
||||||
@@ -98,30 +96,6 @@ type internal AdtProduct =
|
|||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal AstHelper =
|
module internal AstHelper =
|
||||||
|
|
||||||
/// Given e.g. "byte", returns "System.Byte".
|
|
||||||
let qualifyPrimitiveType (typeName : string) : LongIdent option =
|
|
||||||
match typeName with
|
|
||||||
| "float32"
|
|
||||||
| "single" -> [ "System" ; "Single" ] |> Some
|
|
||||||
| "float"
|
|
||||||
| "double" -> [ "System" ; "Double" ] |> Some
|
|
||||||
| "byte"
|
|
||||||
| "uint8" -> [ "System" ; "Byte" ] |> Some
|
|
||||||
| "sbyte"
|
|
||||||
| "int8" -> [ "System" ; "SByte" ] |> Some
|
|
||||||
| "int16" -> [ "System" ; "Int16" ] |> Some
|
|
||||||
| "int"
|
|
||||||
| "int32" -> [ "System" ; "Int32" ] |> Some
|
|
||||||
| "int64" -> [ "System" ; "Int64" ] |> Some
|
|
||||||
| "uint16" -> [ "System" ; "UInt16" ] |> Some
|
|
||||||
| "uint"
|
|
||||||
| "uint32" -> [ "System" ; "UInt32" ] |> Some
|
|
||||||
| "uint64" -> [ "System" ; "UInt64" ] |> Some
|
|
||||||
| "char" -> [ "System" ; "Char" ] |> Some
|
|
||||||
| "decimal" -> [ "System" ; "Decimal" ] |> Some
|
|
||||||
| _ -> None
|
|
||||||
|> Option.map (List.map Ident.Create)
|
|
||||||
|
|
||||||
let instantiateRecord (fields : (RecordFieldName * SynExpr option) list) : SynExpr =
|
let instantiateRecord (fields : (RecordFieldName * SynExpr option) list) : SynExpr =
|
||||||
let fields =
|
let fields =
|
||||||
fields
|
fields
|
||||||
@@ -130,86 +104,17 @@ module internal AstHelper =
|
|||||||
SynExpr.Record (None, None, fields, range0)
|
SynExpr.Record (None, None, fields, range0)
|
||||||
|
|
||||||
let defineRecordType (record : RecordType) : SynTypeDefn =
|
let defineRecordType (record : RecordType) : SynTypeDefn =
|
||||||
let repr =
|
|
||||||
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, Seq.toList record.Fields, range0), range0)
|
|
||||||
|
|
||||||
let name =
|
let name =
|
||||||
SynComponentInfo.Create (
|
SynComponentInfo.create record.Name
|
||||||
[ record.Name ],
|
|> SynComponentInfo.setAccessibility record.Accessibility
|
||||||
?xmldoc = record.XmlDoc,
|
|> match record.XmlDoc with
|
||||||
?parameters = record.Generics,
|
| None -> id
|
||||||
access = record.Accessibility
|
| Some doc -> SynComponentInfo.withDocString doc
|
||||||
)
|
|> SynComponentInfo.setGenerics record.Generics
|
||||||
|
|
||||||
let trivia : SynTypeDefnTrivia =
|
SynTypeDefnRepr.record (Seq.toList record.Fields)
|
||||||
{
|
|> SynTypeDefn.create name
|
||||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
|> SynTypeDefn.withMemberDefns (defaultArg record.Members SynMemberDefns.Empty)
|
||||||
EqualsRange = Some range0
|
|
||||||
WithKeyword = Some range0
|
|
||||||
}
|
|
||||||
|
|
||||||
SynTypeDefn (name, repr, defaultArg record.Members SynMemberDefns.Empty, None, range0, trivia)
|
|
||||||
|
|
||||||
let isOptionIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] when System.String.Equals (i.idText, "option", System.StringComparison.OrdinalIgnoreCase) -> true
|
|
||||||
// TODO: consider Microsoft.FSharp.Option or whatever it is
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isUnitIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] when System.String.Equals (i.idText, "unit", System.StringComparison.OrdinalIgnoreCase) -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isListIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true
|
|
||||||
// TODO: consider FSharpList or whatever it is
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isArrayIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] when
|
|
||||||
System.String.Equals (i.idText, "array", System.StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| System.String.Equals (i.idText, "[]", System.StringComparison.Ordinal)
|
|
||||||
->
|
|
||||||
true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isResponseIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "Response" ]
|
|
||||||
| [ "RestEase" ; "Response" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isMapIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "Map" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isReadOnlyDictionaryIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "IReadOnlyDictionary" ]
|
|
||||||
| [ "Generic" ; "IReadOnlyDictionary" ]
|
|
||||||
| [ "Collections" ; "Generic" ; "IReadOnlyDictionary" ]
|
|
||||||
| [ "System" ; "Collections" ; "Generic" ; "IReadOnlyDictionary" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isDictionaryIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "Dictionary" ]
|
|
||||||
| [ "Generic" ; "Dictionary" ]
|
|
||||||
| [ "Collections" ; "Generic" ; "Dictionary" ]
|
|
||||||
| [ "System" ; "Collections" ; "Generic" ; "Dictionary" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isIDictionaryIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "IDictionary" ]
|
|
||||||
| [ "Generic" ; "IDictionary" ]
|
|
||||||
| [ "Collections" ; "Generic" ; "IDictionary" ]
|
|
||||||
| [ "System" ; "Collections" ; "Generic" ; "IDictionary" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list =
|
let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list =
|
||||||
moduleDecls
|
moduleDecls
|
||||||
@@ -231,12 +136,12 @@ module internal AstHelper =
|
|||||||
| SynType.Paren (inner, _) ->
|
| SynType.Paren (inner, _) ->
|
||||||
let result, _ = convertSigParam inner
|
let result, _ = convertSigParam inner
|
||||||
result, true
|
result, true
|
||||||
| SynType.LongIdent ident ->
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
{
|
{
|
||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.CreateLongIdent ident
|
Type = SynType.createLongIdent ident
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
| SynType.SignatureParameter (attrs, opt, id, usedType, _) ->
|
| SynType.SignatureParameter (attrs, opt, id, usedType, _) ->
|
||||||
@@ -254,7 +159,7 @@ module internal AstHelper =
|
|||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.Var (typar, range0)
|
Type = SynType.var typar
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
| _ -> failwithf "expected SignatureParameter, got: %+A" ty
|
| _ -> failwithf "expected SignatureParameter, got: %+A" ty
|
||||||
@@ -285,7 +190,7 @@ module internal AstHelper =
|
|||||||
|
|
||||||
let toFun (inputs : SynType list) (ret : SynType) : SynType =
|
let toFun (inputs : SynType list) (ret : SynType) : SynType =
|
||||||
(ret, List.rev inputs)
|
(ret, List.rev inputs)
|
||||||
||> List.fold (fun ty input -> SynType.CreateFun (input, ty))
|
||> List.fold (fun ty input -> SynType.funFromDomain input ty)
|
||||||
|
|
||||||
/// Returns the args (where these are tuple types if curried) in order, and the return type.
|
/// Returns the args (where these are tuple types if curried) in order, and the return type.
|
||||||
let rec getType (ty : SynType) : (SynType * bool) list * SynType =
|
let rec getType (ty : SynType) : (SynType * bool) list * SynType =
|
||||||
@@ -356,7 +261,7 @@ module internal AstHelper =
|
|||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent ident)
|
Type = SynType.createLongIdent ident
|
||||||
}
|
}
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
}
|
}
|
||||||
@@ -368,7 +273,7 @@ module internal AstHelper =
|
|||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.Var (typar, range0)
|
Type = SynType.var typar
|
||||||
}
|
}
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
}
|
}
|
||||||
@@ -522,190 +427,3 @@ module internal AstHelper =
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
| _ -> failwithf "Failed to get record elements for type that was: %+A" repr
|
| _ -> failwithf "Failed to get record elements for type that was: %+A" repr
|
||||||
|
|
||||||
[<AutoOpen>]
|
|
||||||
module internal SynTypePatterns =
|
|
||||||
let (|OptionType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isOptionIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|UnitType|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident when AstHelper.isUnitIdent ident -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|ListType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isListIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|ArrayType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isArrayIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| SynType.Array (1, innerType, _) -> Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|RestEaseResponseType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isResponseIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|DictionaryType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isDictionaryIdent ident ->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|IDictionaryType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isIDictionaryIdent ident ->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|IReadOnlyDictionaryType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when
|
|
||||||
AstHelper.isReadOnlyDictionaryIdent ident
|
|
||||||
->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|MapType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isMapIdent ident ->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|BigInt|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "bigint" ]
|
|
||||||
| [ "BigInteger" ]
|
|
||||||
| [ "Numerics" ; "BigInteger" ]
|
|
||||||
| [ "System" ; "Numerics" ; "BigInteger" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
/// Returns the type, qualified as in e.g. `System.Boolean`.
|
|
||||||
let (|PrimitiveType|_|) (fieldType : SynType) : LongIdent option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] -> AstHelper.qualifyPrimitiveType i.idText
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|String|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] ->
|
|
||||||
[ "string" ]
|
|
||||||
|> List.tryFind (fun s -> s = i.idText)
|
|
||||||
|> Option.map ignore<string>
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Byte|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] -> [ "byte" ] |> List.tryFind (fun s -> s = i.idText) |> Option.map ignore<string>
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Guid|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Guid" ]
|
|
||||||
| [ "Guid" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|HttpResponseMessage|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Net" ; "Http" ; "HttpResponseMessage" ]
|
|
||||||
| [ "Net" ; "Http" ; "HttpResponseMessage" ]
|
|
||||||
| [ "Http" ; "HttpResponseMessage" ]
|
|
||||||
| [ "HttpResponseMessage" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|HttpContent|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Net" ; "Http" ; "HttpContent" ]
|
|
||||||
| [ "Net" ; "Http" ; "HttpContent" ]
|
|
||||||
| [ "Http" ; "HttpContent" ]
|
|
||||||
| [ "HttpContent" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Stream|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "IO" ; "Stream" ]
|
|
||||||
| [ "IO" ; "Stream" ]
|
|
||||||
| [ "Stream" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|NumberType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] -> [ "string" ; "float" ; "int" ; "bool" ] |> List.tryFind (fun s -> s = i.idText)
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|DateOnly|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "DateOnly" ]
|
|
||||||
| [ "DateOnly" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|DateTime|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "DateTime" ]
|
|
||||||
| [ "DateTime" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Uri|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Uri" ]
|
|
||||||
| [ "Uri" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Task|_|) (fieldType : SynType) : SynType option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)), _, args, _, _, _, _) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "Task" ]
|
|
||||||
| [ "Tasks" ; "Task" ]
|
|
||||||
| [ "Threading" ; "Tasks" ; "Task" ]
|
|
||||||
| [ "System" ; "Threading" ; "Tasks" ; "Task" ] ->
|
|
||||||
match args with
|
|
||||||
| [ arg ] -> Some arg
|
|
||||||
| _ -> failwithf "Expected Task to be applied to exactly one arg, but got: %+A" args
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -82,7 +82,7 @@ module internal HttpClientGenerator =
|
|||||||
let matchingAttrs =
|
let matchingAttrs =
|
||||||
attrs
|
attrs
|
||||||
|> List.choose (fun attr ->
|
|> List.choose (fun attr ->
|
||||||
match attr.TypeName.AsString with
|
match SynLongIdent.toString attr.TypeName with
|
||||||
| "Get"
|
| "Get"
|
||||||
| "GetAttribute"
|
| "GetAttribute"
|
||||||
| "WoofWare.Myriad.Plugins.RestEase.Get"
|
| "WoofWare.Myriad.Plugins.RestEase.Get"
|
||||||
@@ -144,7 +144,7 @@ module internal HttpClientGenerator =
|
|||||||
let extractHeaderInformation (attrs : SynAttribute list) : SynExpr list list =
|
let extractHeaderInformation (attrs : SynAttribute list) : SynExpr list list =
|
||||||
attrs
|
attrs
|
||||||
|> List.choose (fun attr ->
|
|> List.choose (fun attr ->
|
||||||
match attr.TypeName.AsString with
|
match SynLongIdent.toString attr.TypeName with
|
||||||
| "Header"
|
| "Header"
|
||||||
| "RestEase.Header"
|
| "RestEase.Header"
|
||||||
| "WoofWare.Myriad.Plugins.RestEase.Header" ->
|
| "WoofWare.Myriad.Plugins.RestEase.Header" ->
|
||||||
@@ -158,7 +158,7 @@ module internal HttpClientGenerator =
|
|||||||
let shouldAllowAnyStatusCode (attrs : SynAttribute list) : bool =
|
let shouldAllowAnyStatusCode (attrs : SynAttribute list) : bool =
|
||||||
attrs
|
attrs
|
||||||
|> List.exists (fun attr ->
|
|> List.exists (fun attr ->
|
||||||
match attr.TypeName.AsString with
|
match SynLongIdent.toString attr.TypeName with
|
||||||
| "AllowAnyStatusCode"
|
| "AllowAnyStatusCode"
|
||||||
| "AllowAnyStatusCodeAttribute"
|
| "AllowAnyStatusCodeAttribute"
|
||||||
| "RestEase.AllowAnyStatusCode"
|
| "RestEase.AllowAnyStatusCode"
|
||||||
@@ -213,11 +213,7 @@ module internal HttpClientGenerator =
|
|||||||
|
|
||||||
let argType =
|
let argType =
|
||||||
if arg.IsOptional then
|
if arg.IsOptional then
|
||||||
SynType.CreateApp (
|
SynType.appPostfix "option" arg.Type
|
||||||
SynType.CreateLongIdent (SynLongIdent.CreateString "option"),
|
|
||||||
[ arg.Type ],
|
|
||||||
isPostfix = true
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
arg.Type
|
arg.Type
|
||||||
|
|
||||||
@@ -229,25 +225,15 @@ module internal HttpClientGenerator =
|
|||||||
| None -> failwith $"expected an optional cancellation token as final arg in %s{info.Identifier.idText}"
|
| None -> failwith $"expected an optional cancellation token as final arg in %s{info.Identifier.idText}"
|
||||||
| Some (arg, _) -> arg
|
| Some (arg, _) -> arg
|
||||||
|
|
||||||
let argPats =
|
|
||||||
let args = args |> List.map snd
|
|
||||||
|
|
||||||
SynPat.Tuple (false, args, List.replicate (args.Length - 1) range0, range0)
|
|
||||||
|> SynPat.CreateParen
|
|
||||||
|> List.singleton
|
|
||||||
|> SynArgPats.Pats
|
|
||||||
|
|
||||||
let headPat =
|
let headPat =
|
||||||
let thisIdent = if variableHeaders.IsEmpty then "_" else "this"
|
let thisIdent = if variableHeaders.IsEmpty then "_" else "this"
|
||||||
|
|
||||||
SynPat.LongIdent (
|
args
|
||||||
SynLongIdent.CreateFromLongIdent [ Ident.Create thisIdent ; info.Identifier ],
|
|> List.map snd
|
||||||
None,
|
|> SynPat.tuple
|
||||||
None,
|
|> List.singleton
|
||||||
argPats,
|
|> SynArgPats.Pats
|
||||||
None,
|
|> SynPat.identWithArgs [ Ident.create thisIdent ; info.Identifier ]
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
let requestUriTrailer =
|
let requestUriTrailer =
|
||||||
(info.UrlTemplate, info.Args)
|
(info.UrlTemplate, info.Args)
|
||||||
@@ -269,10 +255,10 @@ module internal HttpClientGenerator =
|
|||||||
template
|
template
|
||||||
|> SynExpr.callMethodArg
|
|> SynExpr.callMethodArg
|
||||||
"Replace"
|
"Replace"
|
||||||
(SynExpr.CreateParenedTuple
|
(SynExpr.tuple
|
||||||
[
|
[
|
||||||
SynExpr.CreateConstString ("{" + substituteId + "}")
|
SynExpr.CreateConst ("{" + substituteId + "}")
|
||||||
SynExpr.callMethod "ToString" (SynExpr.CreateIdent varName)
|
SynExpr.callMethod "ToString" (SynExpr.createIdent' varName)
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
||||||
)
|
)
|
||||||
@@ -314,30 +300,27 @@ module internal HttpClientGenerator =
|
|||||||
let urlSeparator =
|
let urlSeparator =
|
||||||
// apparent Myriad bug: `IndexOf '?'` gets formatted as `IndexOf ?` which is clearly wrong
|
// apparent Myriad bug: `IndexOf '?'` gets formatted as `IndexOf ?` which is clearly wrong
|
||||||
let questionMark =
|
let questionMark =
|
||||||
SynExpr.CreateConst (SynConst.Int32 63)
|
SynExpr.CreateConst 63
|
||||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "char")
|
|> SynExpr.applyFunction (SynExpr.createIdent "char")
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|
|
||||||
let containsQuestion =
|
let containsQuestion =
|
||||||
info.UrlTemplate
|
info.UrlTemplate
|
||||||
|> SynExpr.callMethodArg "IndexOf" questionMark
|
|> SynExpr.callMethodArg "IndexOf" questionMark
|
||||||
|> SynExpr.greaterThanOrEqual (SynExpr.CreateConst (SynConst.Int32 0))
|
|> SynExpr.greaterThanOrEqual (SynExpr.CreateConst 0)
|
||||||
|
|
||||||
SynExpr.ifThenElse
|
SynExpr.ifThenElse containsQuestion (SynExpr.CreateConst "?") (SynExpr.CreateConst "&")
|
||||||
containsQuestion
|
|> SynExpr.paren
|
||||||
(SynExpr.CreateConst (SynConst.CreateString "?"))
|
|
||||||
(SynExpr.CreateConst (SynConst.CreateString "&"))
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|
|
||||||
let prefix =
|
let prefix =
|
||||||
SynExpr.CreateIdent firstValueId
|
SynExpr.createIdent' firstValueId
|
||||||
|> SynExpr.toString firstValue.Type
|
|> SynExpr.toString firstValue.Type
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ])
|
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
||||||
)
|
)
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|> SynExpr.plus (SynExpr.plus urlSeparator (SynExpr.CreateConstString (firstKey + "=")))
|
|> SynExpr.plus (SynExpr.plus urlSeparator (SynExpr.CreateConst (firstKey + "=")))
|
||||||
|
|
||||||
(prefix, queryParams)
|
(prefix, queryParams)
|
||||||
||> List.fold (fun uri (paramKey, paramValue) ->
|
||> List.fold (fun uri (paramKey, paramValue) ->
|
||||||
@@ -346,16 +329,16 @@ module internal HttpClientGenerator =
|
|||||||
| None -> failwith "Unable to get parameter variable name from anonymous parameter"
|
| None -> failwith "Unable to get parameter variable name from anonymous parameter"
|
||||||
| Some id -> id
|
| Some id -> id
|
||||||
|
|
||||||
SynExpr.toString paramValue.Type (SynExpr.CreateIdent paramValueId)
|
SynExpr.toString paramValue.Type (SynExpr.createIdent' paramValueId)
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
||||||
)
|
)
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|> SynExpr.plus (SynExpr.plus uri (SynExpr.CreateConstString ("&" + paramKey + "=")))
|
|> SynExpr.plus (SynExpr.plus uri (SynExpr.CreateConst ("&" + paramKey + "=")))
|
||||||
)
|
)
|
||||||
|> SynExpr.plus requestUriTrailer
|
|> SynExpr.plus requestUriTrailer
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|
|
||||||
let requestUri =
|
let requestUri =
|
||||||
let uriIdent = SynExpr.createLongIdent [ "System" ; "Uri" ]
|
let uriIdent = SynExpr.createLongIdent [ "System" ; "Uri" ]
|
||||||
@@ -364,45 +347,37 @@ module internal HttpClientGenerator =
|
|||||||
|
|
||||||
let baseAddress =
|
let baseAddress =
|
||||||
[
|
[
|
||||||
SynMatchClause.Create (
|
SynMatchClause.create
|
||||||
SynPat.CreateNull,
|
SynPat.createNull
|
||||||
None,
|
(match info.BaseAddress with
|
||||||
match info.BaseAddress with
|
|
||||||
| None ->
|
| None ->
|
||||||
[
|
[
|
||||||
SynExpr.CreateApp (SynExpr.CreateIdentString "nameof", SynExpr.CreateParen baseAddress)
|
SynExpr.applyFunction (SynExpr.createIdent "nameof") (SynExpr.paren baseAddress)
|
||||||
SynExpr.CreateConstString
|
SynExpr.CreateConst
|
||||||
"No base address was supplied on the type, and no BaseAddress was on the HttpClient."
|
"No base address was supplied on the type, and no BaseAddress was on the HttpClient."
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tuple
|
||||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "ArgumentNullException" ])
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "ArgumentNullException" ])
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "raise")
|
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||||
| Some expr -> SynExpr.CreateApp (uriIdent, expr)
|
| Some expr -> SynExpr.applyFunction uriIdent expr)
|
||||||
)
|
SynMatchClause.create (SynPat.named "v") (SynExpr.createIdent "v")
|
||||||
SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, SynExpr.CreateIdentString "v")
|
|
||||||
]
|
]
|
||||||
|> SynExpr.createMatch baseAddress
|
|> SynExpr.createMatch baseAddress
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|
|
||||||
SynExpr.App (
|
|
||||||
ExprAtomicFlag.Atomic,
|
|
||||||
false,
|
|
||||||
uriIdent,
|
|
||||||
SynExpr.CreateParenedTuple
|
|
||||||
[
|
[
|
||||||
baseAddress
|
baseAddress
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
uriIdent,
|
uriIdent
|
||||||
SynExpr.CreateParenedTuple
|
(SynExpr.tuple
|
||||||
[
|
[
|
||||||
requestUriTrailer
|
requestUriTrailer
|
||||||
SynExpr.createLongIdent [ "System" ; "UriKind" ; "Relative" ]
|
SynExpr.createLongIdent [ "System" ; "UriKind" ; "Relative" ]
|
||||||
|
])
|
||||||
]
|
]
|
||||||
)
|
|> SynExpr.tuple
|
||||||
],
|
|> SynExpr.applyFunction uriIdent
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
let bodyParams =
|
let bodyParams =
|
||||||
info.Args
|
info.Args
|
||||||
@@ -436,56 +411,43 @@ module internal HttpClientGenerator =
|
|||||||
let httpReqMessageConstructor =
|
let httpReqMessageConstructor =
|
||||||
[
|
[
|
||||||
SynExpr.equals
|
SynExpr.equals
|
||||||
(SynExpr.CreateIdentString "Method")
|
(SynExpr.createIdent "Method")
|
||||||
(SynExpr.createLongIdent
|
(SynExpr.createLongIdent
|
||||||
[ "System" ; "Net" ; "Http" ; "HttpMethod" ; httpMethodString info.HttpMethod ])
|
[ "System" ; "Net" ; "Http" ; "HttpMethod" ; httpMethodString info.HttpMethod ])
|
||||||
SynExpr.equals (SynExpr.CreateIdentString "RequestUri") (SynExpr.CreateIdentString "uri")
|
SynExpr.equals (SynExpr.createIdent "RequestUri") (SynExpr.createIdent "uri")
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tupleNoParen
|
||||||
|
|
||||||
let returnExpr =
|
let returnExpr =
|
||||||
match info.TaskReturnType with
|
match info.TaskReturnType with
|
||||||
| HttpResponseMessage -> SynExpr.CreateIdentString "response"
|
| HttpResponseMessage -> SynExpr.createIdent "response"
|
||||||
| String -> SynExpr.CreateIdentString "responseString"
|
| String -> SynExpr.createIdent "responseString"
|
||||||
| Stream -> SynExpr.CreateIdentString "responseStream"
|
| Stream -> SynExpr.createIdent "responseStream"
|
||||||
| RestEaseResponseType contents ->
|
| RestEaseResponseType contents ->
|
||||||
let deserialiser =
|
let deserialiser =
|
||||||
SynExpr.CreateLambda (
|
|
||||||
[ SynPat.CreateConst SynConst.Unit ],
|
|
||||||
SynExpr.CreateParen (
|
|
||||||
JsonParseGenerator.parseNode
|
JsonParseGenerator.parseNode
|
||||||
None
|
None
|
||||||
JsonParseGenerator.JsonParseOption.None
|
JsonParseGenerator.JsonParseOption.None
|
||||||
contents
|
contents
|
||||||
(SynExpr.CreateIdentString "jsonNode")
|
(SynExpr.createIdent "jsonNode")
|
||||||
)
|
|> SynExpr.paren
|
||||||
)
|
|> SynExpr.createThunk
|
||||||
|
|
||||||
// new RestEase.Response (content : string, response : HttpResponseMessage, deserialiser : unit -> 'T)
|
// new RestEase.Response (content : string, response : HttpResponseMessage, deserialiser : unit -> 'T)
|
||||||
SynExpr.New (
|
SynExpr.createNew
|
||||||
false,
|
(SynType.app' (SynType.createLongIdent' [ "RestEase" ; "Response" ]) [ SynType.Anon range0 ])
|
||||||
SynType.App (
|
(SynExpr.CreateTuple
|
||||||
SynType.CreateLongIdent (SynLongIdent.Create [ "RestEase" ; "Response" ]),
|
|
||||||
Some range0,
|
|
||||||
[ SynType.Anon range0 ],
|
|
||||||
[],
|
|
||||||
Some range0,
|
|
||||||
false,
|
|
||||||
range0
|
|
||||||
),
|
|
||||||
SynExpr.CreateParenedTuple
|
|
||||||
[
|
[
|
||||||
SynExpr.CreateIdentString "responseString"
|
SynExpr.createIdent "responseString"
|
||||||
SynExpr.CreateIdentString "response"
|
SynExpr.createIdent "response"
|
||||||
SynExpr.CreateParen deserialiser
|
deserialiser
|
||||||
],
|
])
|
||||||
range0
|
|
||||||
)
|
|
||||||
| retType ->
|
| retType ->
|
||||||
JsonParseGenerator.parseNode
|
JsonParseGenerator.parseNode
|
||||||
None
|
None
|
||||||
JsonParseGenerator.JsonParseOption.None
|
JsonParseGenerator.JsonParseOption.None
|
||||||
retType
|
retType
|
||||||
(SynExpr.CreateIdentString "jsonNode")
|
(SynExpr.createIdent "jsonNode")
|
||||||
|
|
||||||
let handleBodyParams =
|
let handleBodyParams =
|
||||||
match bodyParam with
|
match bodyParam with
|
||||||
@@ -498,20 +460,15 @@ module internal HttpClientGenerator =
|
|||||||
[
|
[
|
||||||
Let (
|
Let (
|
||||||
"queryParams",
|
"queryParams",
|
||||||
SynExpr.New (
|
SynExpr.createNew
|
||||||
false,
|
(SynType.createLongIdent'
|
||||||
SynType.CreateLongIdent (
|
[ "System" ; "Net" ; "Http" ; (bodyParamType : BodyParamMethods).ToString () ])
|
||||||
SynLongIdent.Create
|
(SynExpr.createIdent' bodyParamName)
|
||||||
[ "System" ; "Net" ; "Http" ; (bodyParamType : BodyParamMethods).ToString () ]
|
|
||||||
),
|
|
||||||
SynExpr.CreateParen (SynExpr.CreateIdent bodyParamName),
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
Do (
|
Do (
|
||||||
SynExpr.LongIdentSet (
|
SynExpr.LongIdentSet (
|
||||||
SynLongIdent.Create [ "httpMessage" ; "Content" ],
|
SynLongIdent.createS' [ "httpMessage" ; "Content" ],
|
||||||
SynExpr.CreateIdentString "queryParams",
|
SynExpr.createIdent "queryParams",
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -520,8 +477,8 @@ module internal HttpClientGenerator =
|
|||||||
[
|
[
|
||||||
Do (
|
Do (
|
||||||
SynExpr.LongIdentSet (
|
SynExpr.LongIdentSet (
|
||||||
SynLongIdent.Create [ "httpMessage" ; "Content" ],
|
SynLongIdent.createS' [ "httpMessage" ; "Content" ],
|
||||||
SynExpr.CreateIdent bodyParamName,
|
SynExpr.createIdent' bodyParamName,
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -530,38 +487,27 @@ module internal HttpClientGenerator =
|
|||||||
[
|
[
|
||||||
Let (
|
Let (
|
||||||
"queryParams",
|
"queryParams",
|
||||||
SynExpr.New (
|
SynExpr.createNew
|
||||||
false,
|
(SynType.createLongIdent' [ "System" ; "Net" ; "Http" ; "StringContent" ])
|
||||||
SynType.CreateLongIdent (
|
(SynExpr.createIdent' bodyParamName
|
||||||
SynLongIdent.Create [ "System" ; "Net" ; "Http" ; "StringContent" ]
|
|
||||||
),
|
|
||||||
SynExpr.CreateParen (
|
|
||||||
SynExpr.CreateIdent bodyParamName
|
|
||||||
|> SynExpr.pipeThroughFunction (JsonSerializeGenerator.serializeNode ty)
|
|> SynExpr.pipeThroughFunction (JsonSerializeGenerator.serializeNode ty)
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.createLambda
|
SynExpr.createLambda
|
||||||
"node"
|
"node"
|
||||||
(SynExpr.ifThenElse
|
(SynExpr.ifThenElse
|
||||||
(SynExpr.CreateApp (
|
(SynExpr.applyFunction
|
||||||
SynExpr.CreateIdentString "isNull",
|
(SynExpr.createIdent "isNull")
|
||||||
SynExpr.CreateIdentString "node"
|
(SynExpr.createIdent "node"))
|
||||||
|
(SynExpr.applyFunction
|
||||||
|
(SynExpr.createLongIdent [ "node" ; "ToJsonString" ])
|
||||||
|
(SynExpr.CreateConst ()))
|
||||||
|
(SynExpr.CreateConst "null"))
|
||||||
))
|
))
|
||||||
(SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.Create [ "node" ; "ToJsonString" ]
|
|
||||||
),
|
|
||||||
SynExpr.CreateConst SynConst.Unit
|
|
||||||
))
|
|
||||||
(SynExpr.CreateConst (SynConst.CreateString "null")))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
Do (
|
Do (
|
||||||
SynExpr.LongIdentSet (
|
SynExpr.LongIdentSet (
|
||||||
SynLongIdent.Create [ "httpMessage" ; "Content" ],
|
SynLongIdent.createS' [ "httpMessage" ; "Content" ],
|
||||||
SynExpr.CreateIdent (Ident.Create "queryParams"),
|
SynExpr.createIdent "queryParams",
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -572,10 +518,9 @@ module internal HttpClientGenerator =
|
|||||||
LetBang (
|
LetBang (
|
||||||
"responseString",
|
"responseString",
|
||||||
SynExpr.awaitTask (
|
SynExpr.awaitTask (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStringAsync" ],
|
(SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStringAsync" ])
|
||||||
SynExpr.CreateIdentString "ct"
|
(SynExpr.createIdent "ct")
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -583,10 +528,9 @@ module internal HttpClientGenerator =
|
|||||||
LetBang (
|
LetBang (
|
||||||
"responseStream",
|
"responseStream",
|
||||||
SynExpr.awaitTask (
|
SynExpr.awaitTask (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStreamAsync" ],
|
(SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStreamAsync" ])
|
||||||
SynExpr.CreateIdentString "ct"
|
(SynExpr.createIdent "ct")
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -594,47 +538,39 @@ module internal HttpClientGenerator =
|
|||||||
LetBang (
|
LetBang (
|
||||||
"jsonNode",
|
"jsonNode",
|
||||||
SynExpr.awaitTask (
|
SynExpr.awaitTask (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ; "ParseAsync" ],
|
(SynExpr.createLongIdent
|
||||||
SynExpr.CreateParenedTuple
|
[ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ; "ParseAsync" ])
|
||||||
|
(SynExpr.tuple
|
||||||
[
|
[
|
||||||
SynExpr.CreateIdentString "responseStream"
|
SynExpr.createIdent "responseStream"
|
||||||
SynExpr.equals
|
SynExpr.equals (SynExpr.createIdent "cancellationToken") (SynExpr.createIdent "ct")
|
||||||
(SynExpr.CreateIdentString "cancellationToken")
|
])
|
||||||
(SynExpr.CreateIdentString "ct")
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
let setVariableHeaders =
|
let setVariableHeaders =
|
||||||
variableHeaders
|
variableHeaders
|
||||||
|> List.map (fun (headerName, callToGetValue) ->
|
|> List.map (fun (headerName, callToGetValue) ->
|
||||||
Do (
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ],
|
|
||||||
SynExpr.CreateParenedTuple
|
|
||||||
[
|
[
|
||||||
headerName
|
headerName
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent'
|
(SynExpr.createLongIdent'
|
||||||
[ Ident.Create "this" ; callToGetValue ; Ident.Create "ToString" ],
|
[ Ident.create "this" ; callToGetValue ; Ident.create "ToString" ])
|
||||||
SynExpr.CreateConst SynConst.Unit
|
(SynExpr.CreateConst ())
|
||||||
)
|
|
||||||
]
|
]
|
||||||
)
|
|> SynExpr.tuple
|
||||||
)
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ])
|
||||||
|
|> Do
|
||||||
)
|
)
|
||||||
|
|
||||||
let setConstantHeaders =
|
let setConstantHeaders =
|
||||||
constantHeaders
|
constantHeaders
|
||||||
|> List.map (fun (headerName, headerValue) ->
|
|> List.map (fun (headerName, headerValue) ->
|
||||||
Do (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateApp (
|
(SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ])
|
||||||
SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ],
|
(SynExpr.tuple [ headerName ; headerValue ])
|
||||||
SynExpr.CreateParenedTuple [ headerName ; headerValue ]
|
|> Do
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
[
|
[
|
||||||
@@ -643,14 +579,9 @@ module internal HttpClientGenerator =
|
|||||||
yield
|
yield
|
||||||
Use (
|
Use (
|
||||||
"httpMessage",
|
"httpMessage",
|
||||||
SynExpr.New (
|
SynExpr.createNew
|
||||||
false,
|
(SynType.createLongIdent' [ "System" ; "Net" ; "Http" ; "HttpRequestMessage" ])
|
||||||
SynType.CreateLongIdent (
|
httpReqMessageConstructor
|
||||||
SynLongIdent.Create [ "System" ; "Net" ; "Http" ; "HttpRequestMessage" ]
|
|
||||||
),
|
|
||||||
httpReqMessageConstructor,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
yield! handleBodyParams
|
yield! handleBodyParams
|
||||||
@@ -662,21 +593,18 @@ module internal HttpClientGenerator =
|
|||||||
LetBang (
|
LetBang (
|
||||||
"response",
|
"response",
|
||||||
SynExpr.awaitTask (
|
SynExpr.awaitTask (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent [ "client" ; "SendAsync" ],
|
(SynExpr.createLongIdent [ "client" ; "SendAsync" ])
|
||||||
SynExpr.CreateParenedTuple
|
(SynExpr.tuple [ SynExpr.createIdent "httpMessage" ; SynExpr.createIdent "ct" ])
|
||||||
[ SynExpr.CreateIdentString "httpMessage" ; SynExpr.CreateIdentString "ct" ]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if info.EnsureSuccessHttpCode then
|
if info.EnsureSuccessHttpCode then
|
||||||
yield
|
yield
|
||||||
Let (
|
Let (
|
||||||
"response",
|
"response",
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent [ "response" ; "EnsureSuccessStatusCode" ],
|
(SynExpr.createLongIdent [ "response" ; "EnsureSuccessStatusCode" ])
|
||||||
SynExpr.CreateConst SynConst.Unit
|
(SynExpr.CreateConst ())
|
||||||
)
|
|
||||||
)
|
)
|
||||||
match info.TaskReturnType with
|
match info.TaskReturnType with
|
||||||
| HttpResponseMessage -> ()
|
| HttpResponseMessage -> ()
|
||||||
@@ -691,7 +619,7 @@ module internal HttpClientGenerator =
|
|||||||
yield jsonNode
|
yield jsonNode
|
||||||
]
|
]
|
||||||
|> SynExpr.createCompExpr "async" returnExpr
|
|> SynExpr.createCompExpr "async" returnExpr
|
||||||
|> SynExpr.startAsTask (SynLongIdent.CreateFromLongIdent [ cancellationTokenArg ])
|
|> SynExpr.startAsTask cancellationTokenArg
|
||||||
|
|
||||||
SynBinding.SynBinding (
|
SynBinding.SynBinding (
|
||||||
None,
|
None,
|
||||||
@@ -714,7 +642,7 @@ module internal HttpClientGenerator =
|
|||||||
let getHttpAttributes (attrs : SynAttribute list) : HttpAttribute list =
|
let getHttpAttributes (attrs : SynAttribute list) : HttpAttribute list =
|
||||||
attrs
|
attrs
|
||||||
|> List.choose (fun attr ->
|
|> List.choose (fun attr ->
|
||||||
match attr.TypeName.AsString with
|
match SynLongIdent.toString attr.TypeName with
|
||||||
| "RestEase.Query"
|
| "RestEase.Query"
|
||||||
| "RestEase.QueryAttribute"
|
| "RestEase.QueryAttribute"
|
||||||
| "WoofWare.Myriad.Plugins.RestEase.Query"
|
| "WoofWare.Myriad.Plugins.RestEase.Query"
|
||||||
@@ -755,7 +683,7 @@ module internal HttpClientGenerator =
|
|||||||
let extractBasePath (attrs : SynAttribute list) : SynExpr option =
|
let extractBasePath (attrs : SynAttribute list) : SynExpr option =
|
||||||
attrs
|
attrs
|
||||||
|> List.tryPick (fun attr ->
|
|> List.tryPick (fun attr ->
|
||||||
match attr.TypeName.AsString with
|
match SynLongIdent.toString attr.TypeName with
|
||||||
| "BasePath"
|
| "BasePath"
|
||||||
| "RestEase.BasePath"
|
| "RestEase.BasePath"
|
||||||
| "WoofWare.Myriad.Plugins.RestEase.BasePath"
|
| "WoofWare.Myriad.Plugins.RestEase.BasePath"
|
||||||
@@ -768,7 +696,7 @@ module internal HttpClientGenerator =
|
|||||||
let extractBaseAddress (attrs : SynAttribute list) : SynExpr option =
|
let extractBaseAddress (attrs : SynAttribute list) : SynExpr option =
|
||||||
attrs
|
attrs
|
||||||
|> List.tryPick (fun attr ->
|
|> List.tryPick (fun attr ->
|
||||||
match attr.TypeName.AsString with
|
match SynLongIdent.toString attr.TypeName with
|
||||||
| "BaseAddress"
|
| "BaseAddress"
|
||||||
| "RestEase.BaseAddress"
|
| "RestEase.BaseAddress"
|
||||||
| "WoofWare.Myriad.Plugins.RestEase.BaseAddress"
|
| "WoofWare.Myriad.Plugins.RestEase.BaseAddress"
|
||||||
@@ -904,15 +832,11 @@ module internal HttpClientGenerator =
|
|||||||
SynValInfo.SynValInfo ([ [ SynArgInfo.Empty ] ; [] ], SynArgInfo.Empty),
|
SynValInfo.SynValInfo ([ [ SynArgInfo.Empty ] ; [] ], SynArgInfo.Empty),
|
||||||
None
|
None
|
||||||
),
|
),
|
||||||
SynPat.CreateLongIdent (
|
SynPat.CreateLongIdent (SynLongIdent.create [ Ident.create "_" ; pi.Identifier ], []),
|
||||||
SynLongIdent.CreateFromLongIdent [ Ident.Create "_" ; pi.Identifier ],
|
|
||||||
[]
|
|
||||||
),
|
|
||||||
Some (SynBindingReturnInfo.Create pi.Type),
|
Some (SynBindingReturnInfo.Create pi.Type),
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent' [ Ident.lowerFirstLetter pi.Identifier ],
|
(SynExpr.createLongIdent' [ Ident.lowerFirstLetter pi.Identifier ])
|
||||||
SynExpr.CreateConst SynConst.Unit
|
(SynExpr.CreateConst ()),
|
||||||
),
|
|
||||||
range0,
|
range0,
|
||||||
DebugPointAtBinding.Yes range0,
|
DebugPointAtBinding.Yes range0,
|
||||||
{
|
{
|
||||||
@@ -933,11 +857,11 @@ module internal HttpClientGenerator =
|
|||||||
else
|
else
|
||||||
"Module")
|
"Module")
|
||||||
|> sprintf "%s for constructing a REST client."
|
|> sprintf "%s for constructing a REST client."
|
||||||
|> PreXmlDoc.Create
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let interfaceImpl =
|
let interfaceImpl =
|
||||||
SynExpr.ObjExpr (
|
SynExpr.ObjExpr (
|
||||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name),
|
SynType.createLongIdent interfaceType.Name,
|
||||||
None,
|
None,
|
||||||
Some range0,
|
Some range0,
|
||||||
[],
|
[],
|
||||||
@@ -950,28 +874,22 @@ module internal HttpClientGenerator =
|
|||||||
let headerArgs =
|
let headerArgs =
|
||||||
properties
|
properties
|
||||||
|> List.map (fun (_, pi) ->
|
|> List.map (fun (_, pi) ->
|
||||||
SynPat.CreateTyped (
|
SynPat.namedI (Ident.lowerFirstLetter pi.Identifier)
|
||||||
SynPat.CreateNamed (Ident.lowerFirstLetter pi.Identifier),
|
|> SynPat.annotateType (SynType.funFromDomain (SynType.named "unit") pi.Type)
|
||||||
SynType.CreateFun (SynType.CreateLongIdent "unit", pi.Type)
|
|
||||||
)
|
|
||||||
|> SynPat.CreateParen
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let clientCreationArg =
|
let clientCreationArg =
|
||||||
SynPat.CreateTyped (
|
SynPat.named "client"
|
||||||
SynPat.CreateNamed (Ident.Create "client"),
|
|> SynPat.annotateType (SynType.createLongIdent' [ "System" ; "Net" ; "Http" ; "HttpClient" ])
|
||||||
SynType.CreateLongIdent (SynLongIdent.Create [ "System" ; "Net" ; "Http" ; "HttpClient" ])
|
|
||||||
)
|
|
||||||
|> SynPat.CreateParen
|
|
||||||
|
|
||||||
let xmlDoc =
|
let xmlDoc =
|
||||||
if properties.IsEmpty then
|
if properties.IsEmpty then
|
||||||
"Create a REST client."
|
"Create a REST client."
|
||||||
else
|
else
|
||||||
"Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties."
|
"Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties."
|
||||||
|> PreXmlDoc.Create
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let functionName = Ident.Create "client"
|
let functionName = Ident.create "client"
|
||||||
|
|
||||||
let valData =
|
let valData =
|
||||||
let memberFlags =
|
let memberFlags =
|
||||||
@@ -994,10 +912,9 @@ module internal HttpClientGenerator =
|
|||||||
None
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
let pattern = SynLongIdent.CreateString "make"
|
let pattern = SynLongIdent.createS "make"
|
||||||
|
|
||||||
let returnInfo =
|
let returnInfo = SynType.createLongIdent interfaceType.Name
|
||||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name)
|
|
||||||
|
|
||||||
let nameWithoutLeadingI =
|
let nameWithoutLeadingI =
|
||||||
List.last interfaceType.Name
|
List.last interfaceType.Name
|
||||||
@@ -1011,64 +928,46 @@ module internal HttpClientGenerator =
|
|||||||
let createFunc =
|
let createFunc =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
let binding =
|
let binding =
|
||||||
SynBinding.basic
|
SynBinding.basic [ Ident.create "make" ] (headerArgs @ [ clientCreationArg ]) interfaceImpl
|
||||||
(SynLongIdent.CreateString "make")
|
|
||||||
(headerArgs @ [ clientCreationArg ])
|
|
||||||
interfaceImpl
|
|
||||||
|> SynBinding.withXmlDoc xmlDoc
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|> SynBinding.makeStaticMember
|
|
||||||
|> SynBinding.withReturnAnnotation returnInfo
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|
|> SynMemberDefn.staticMember
|
||||||
|
|
||||||
let mem = SynMemberDefn.Member (binding, range0)
|
let componentInfo =
|
||||||
|
SynComponentInfo.create (Ident.create nameWithoutLeadingI)
|
||||||
|
|> SynComponentInfo.withDocString (PreXmlDoc.create "Extension methods for HTTP clients")
|
||||||
|
|
||||||
let containingType =
|
let containingType =
|
||||||
SynTypeDefn.SynTypeDefn (
|
SynTypeDefnRepr.augmentation ()
|
||||||
SynComponentInfo.Create (
|
|> SynTypeDefn.create componentInfo
|
||||||
[ Ident.Create nameWithoutLeadingI ],
|
|> SynTypeDefn.withMemberDefns [ binding ]
|
||||||
xmldoc = PreXmlDoc.Create " Extension methods for HTTP clients"
|
|
||||||
),
|
|
||||||
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0),
|
|
||||||
[ mem ],
|
|
||||||
None,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
|
||||||
EqualsRange = None
|
|
||||||
WithKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
SynModuleDecl.Types ([ containingType ], range0)
|
SynModuleDecl.Types ([ containingType ], range0)
|
||||||
|
|
||||||
else
|
else
|
||||||
SynBinding.basic (SynLongIdent.CreateString "make") (headerArgs @ [ clientCreationArg ]) interfaceImpl
|
SynBinding.basic [ Ident.create "make" ] (headerArgs @ [ clientCreationArg ]) interfaceImpl
|
||||||
|> SynBinding.withXmlDoc xmlDoc
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|> SynBinding.withReturnAnnotation returnInfo
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
|> SynModuleDecl.CreateLet
|
|> SynModuleDecl.CreateLet
|
||||||
|
|
||||||
let moduleName : LongIdent =
|
let moduleName =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
[ Ident.Create (nameWithoutLeadingI + "HttpClientExtension") ]
|
Ident.create (nameWithoutLeadingI + "HttpClientExtension")
|
||||||
else
|
else
|
||||||
[ Ident.Create nameWithoutLeadingI ]
|
Ident.create nameWithoutLeadingI
|
||||||
|
|
||||||
let attribs =
|
let attribs =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
[ SynAttribute.autoOpen ]
|
||||||
else
|
else
|
||||||
[
|
[ SynAttribute.compilationRepresentation ; SynAttribute.requireQualifiedAccess ]
|
||||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
|
||||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
|
||||||
]
|
|
||||||
|
|
||||||
let modInfo =
|
let modInfo =
|
||||||
SynComponentInfo.Create (
|
SynComponentInfo.create moduleName
|
||||||
moduleName,
|
|> SynComponentInfo.withDocString docString
|
||||||
attributes = attribs,
|
|> SynComponentInfo.addAttributes attribs
|
||||||
xmldoc = docString,
|
|> SynComponentInfo.setAccessibility interfaceType.Accessibility
|
||||||
access = interfaceType.Accessibility
|
|
||||||
)
|
|
||||||
|
|
||||||
SynModuleOrNamespace.CreateNamespace (
|
SynModuleOrNamespace.CreateNamespace (
|
||||||
ns,
|
ns,
|
||||||
|
@@ -48,57 +48,47 @@ module internal InterfaceMockGenerator =
|
|||||||
|
|
||||||
let failwithFun =
|
let failwithFun =
|
||||||
SynExpr.createLongIdent [ "System" ; "NotImplementedException" ]
|
SynExpr.createLongIdent [ "System" ; "NotImplementedException" ]
|
||||||
|> SynExpr.applyTo (SynExpr.CreateConstString "Unimplemented mock function")
|
|> SynExpr.applyTo (SynExpr.CreateConst "Unimplemented mock function")
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "raise")
|
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||||
|> SynExpr.createLambda "_"
|
|> SynExpr.createLambda "_"
|
||||||
|
|
||||||
let constructorReturnType =
|
let constructorReturnType =
|
||||||
match interfaceType.Generics with
|
match interfaceType.Generics with
|
||||||
| None -> SynType.CreateLongIdent name
|
| None -> SynType.createLongIdent' [ name ]
|
||||||
| Some generics ->
|
| Some generics ->
|
||||||
|
|
||||||
let generics =
|
let generics =
|
||||||
generics.TyparDecls
|
generics.TyparDecls
|
||||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||||
|
|
||||||
SynType.App (
|
SynType.app name generics
|
||||||
SynType.CreateLongIdent name,
|
|
||||||
Some range0,
|
|
||||||
generics,
|
|
||||||
List.replicate (generics.Length - 1) range0,
|
|
||||||
Some range0,
|
|
||||||
false,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
let constructorFields =
|
let constructorFields =
|
||||||
let extras =
|
let extras =
|
||||||
if inherits.Contains KnownInheritance.IDisposable then
|
if inherits.Contains KnownInheritance.IDisposable then
|
||||||
let unitFun = SynExpr.createLambda "_" SynExpr.CreateUnit
|
let unitFun = SynExpr.createThunk (SynExpr.CreateConst ())
|
||||||
|
|
||||||
[
|
[ (SynLongIdent.createS "Dispose", true), Some unitFun ]
|
||||||
(SynLongIdent.CreateFromLongIdent [ Ident.Create "Dispose" ], true), Some unitFun
|
|
||||||
]
|
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
|
|
||||||
let nonExtras =
|
let nonExtras =
|
||||||
fields
|
fields
|
||||||
|> List.map (fun field -> (SynLongIdent.CreateFromLongIdent [ getName field ], true), Some failwithFun)
|
|> List.map (fun field -> (SynLongIdent.createI (getName field), true), Some failwithFun)
|
||||||
|
|
||||||
extras @ nonExtras
|
extras @ nonExtras
|
||||||
|
|
||||||
let constructor =
|
let constructor =
|
||||||
SynBinding.basic
|
SynBinding.basic
|
||||||
(SynLongIdent.CreateString "Empty")
|
[ Ident.create "Empty" ]
|
||||||
(if interfaceType.Generics.IsNone then
|
(if interfaceType.Generics.IsNone then
|
||||||
[]
|
[]
|
||||||
else
|
else
|
||||||
[ SynPat.CreateConst SynConst.Unit ])
|
[ SynPat.unit ])
|
||||||
(AstHelper.instantiateRecord constructorFields)
|
(AstHelper.instantiateRecord constructorFields)
|
||||||
|> SynBinding.makeStaticMember
|
|> SynBinding.makeStaticMember
|
||||||
|> SynBinding.withXmlDoc (PreXmlDoc.Create " An implementation where every method throws.")
|
|> SynBinding.withXmlDoc (PreXmlDoc.create "An implementation where every method throws.")
|
||||||
|> SynBinding.withReturnAnnotation constructorReturnType
|
|> SynBinding.withReturnAnnotation constructorReturnType
|
||||||
|> fun m -> SynMemberDefn.Member (m, range0)
|
|> fun m -> SynMemberDefn.Member (m, range0)
|
||||||
|
|
||||||
@@ -107,9 +97,9 @@ module internal InterfaceMockGenerator =
|
|||||||
if inherits.Contains KnownInheritance.IDisposable then
|
if inherits.Contains KnownInheritance.IDisposable then
|
||||||
[
|
[
|
||||||
SynField.Create (
|
SynField.Create (
|
||||||
SynType.CreateFun (SynType.CreateUnit, SynType.CreateUnit),
|
SynType.funFromDomain SynType.unit SynType.unit,
|
||||||
Ident.Create "Dispose",
|
Ident.create "Dispose",
|
||||||
xmldoc = PreXmlDoc.Create " Implementation of IDisposable.Dispose"
|
xmldoc = PreXmlDoc.create "Implementation of IDisposable.Dispose"
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else
|
else
|
||||||
@@ -169,22 +159,20 @@ module internal InterfaceMockGenerator =
|
|||||||
tupledArgs.Args
|
tupledArgs.Args
|
||||||
|> List.mapi (fun j ty ->
|
|> List.mapi (fun j ty ->
|
||||||
match ty.Type with
|
match ty.Type with
|
||||||
| UnitType -> SynPat.Const (SynConst.Unit, range0)
|
| UnitType -> SynPat.unit
|
||||||
| _ -> SynPat.CreateNamed (Ident.Create $"arg_%i{i}_%i{j}")
|
| _ -> SynPat.named $"arg_%i{i}_%i{j}"
|
||||||
)
|
)
|
||||||
|
|
||||||
match args with
|
match args with
|
||||||
| [] -> failwith "somehow got no args at all"
|
| [] -> failwith "somehow got no args at all"
|
||||||
| [ arg ] -> arg
|
| [ arg ] -> arg
|
||||||
| args ->
|
| args -> SynPat.tuple args
|
||||||
SynPat.Tuple (false, args, List.replicate (args.Length - 1) range0, range0)
|
|> fun i -> if tupledArgs.HasParen then SynPat.paren i else i
|
||||||
|> SynPat.CreateParen
|
|
||||||
|> fun i -> if tupledArgs.HasParen then SynPat.Paren (i, range0) else i
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let headPat =
|
let headPat =
|
||||||
SynPat.LongIdent (
|
SynPat.LongIdent (
|
||||||
SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; memberInfo.Identifier ],
|
SynLongIdent.create [ Ident.create "this" ; memberInfo.Identifier ],
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
SynArgPats.Pats headArgs,
|
SynArgPats.Pats headArgs,
|
||||||
@@ -199,10 +187,10 @@ module internal InterfaceMockGenerator =
|
|||||||
args.Args
|
args.Args
|
||||||
|> List.mapi (fun j arg ->
|
|> List.mapi (fun j arg ->
|
||||||
match arg.Type with
|
match arg.Type with
|
||||||
| UnitType -> SynExpr.CreateConst SynConst.Unit
|
| UnitType -> SynExpr.CreateConst ()
|
||||||
| _ -> SynExpr.CreateIdentString $"arg_%i{i}_%i{j}"
|
| _ -> SynExpr.createIdent $"arg_%i{i}_%i{j}"
|
||||||
)
|
)
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tuple
|
||||||
)
|
)
|
||||||
|
|
||||||
match tuples |> List.rev with
|
match tuples |> List.rev with
|
||||||
@@ -210,9 +198,9 @@ module internal InterfaceMockGenerator =
|
|||||||
| last :: rest ->
|
| last :: rest ->
|
||||||
|
|
||||||
(last, rest)
|
(last, rest)
|
||||||
||> List.fold (fun trail next -> SynExpr.CreateApp (next, trail))
|
||> List.fold SynExpr.applyTo
|
||||||
|> SynExpr.applyFunction (
|
|> SynExpr.applyFunction (
|
||||||
SynExpr.createLongIdent' [ Ident.Create "this" ; memberInfo.Identifier ]
|
SynExpr.createLongIdent' [ Ident.create "this" ; memberInfo.Identifier ]
|
||||||
)
|
)
|
||||||
|
|
||||||
SynMemberDefn.Member (
|
SynMemberDefn.Member (
|
||||||
@@ -240,8 +228,7 @@ module internal InterfaceMockGenerator =
|
|||||||
)
|
)
|
||||||
|
|
||||||
let interfaceName =
|
let interfaceName =
|
||||||
let baseName =
|
let baseName = SynType.createLongIdent interfaceType.Name
|
||||||
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name)
|
|
||||||
|
|
||||||
match interfaceType.Generics with
|
match interfaceType.Generics with
|
||||||
| None -> baseName
|
| None -> baseName
|
||||||
@@ -251,17 +238,9 @@ module internal InterfaceMockGenerator =
|
|||||||
| SynTyparDecls.PostfixList (decls, _, _) -> decls
|
| SynTyparDecls.PostfixList (decls, _, _) -> decls
|
||||||
| SynTyparDecls.PrefixList (decls, _) -> decls
|
| SynTyparDecls.PrefixList (decls, _) -> decls
|
||||||
| SynTyparDecls.SinglePrefix (decl, _) -> [ decl ]
|
| SynTyparDecls.SinglePrefix (decl, _) -> [ decl ]
|
||||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||||
|
|
||||||
SynType.App (
|
SynType.app' baseName generics
|
||||||
baseName,
|
|
||||||
Some range0,
|
|
||||||
generics,
|
|
||||||
List.replicate (generics.Length - 1) range0,
|
|
||||||
Some range0,
|
|
||||||
false,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
||||||
|
|
||||||
@@ -280,17 +259,16 @@ module internal InterfaceMockGenerator =
|
|||||||
match inheritance with
|
match inheritance with
|
||||||
| KnownInheritance.IDisposable ->
|
| KnownInheritance.IDisposable ->
|
||||||
let binding =
|
let binding =
|
||||||
SynBinding.basic
|
SynExpr.createLongIdent [ "this" ; "Dispose" ]
|
||||||
(SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; Ident.Create "Dispose" ])
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
[ SynPat.CreateConst SynConst.Unit ]
|
|> SynBinding.basic [ Ident.create "this" ; Ident.create "Dispose" ] [ SynPat.unit ]
|
||||||
(SynExpr.CreateApp (SynExpr.createLongIdent [ "this" ; "Dispose" ], SynExpr.CreateUnit))
|
|> SynBinding.withReturnAnnotation SynType.unit
|
||||||
|> SynBinding.withReturnAnnotation (SynType.Unit ())
|
|
||||||
|> SynBinding.makeInstanceMember
|
|> SynBinding.makeInstanceMember
|
||||||
|
|
||||||
let mem = SynMemberDefn.Member (binding, range0)
|
let mem = SynMemberDefn.Member (binding, range0)
|
||||||
|
|
||||||
SynMemberDefn.Interface (
|
SynMemberDefn.Interface (
|
||||||
SynType.CreateLongIdent (SynLongIdent.Create [ "System" ; "IDisposable" ]),
|
SynType.createLongIdent' [ "System" ; "IDisposable" ],
|
||||||
Some range0,
|
Some range0,
|
||||||
Some [ mem ],
|
Some [ mem ],
|
||||||
range0
|
range0
|
||||||
@@ -300,7 +278,7 @@ module internal InterfaceMockGenerator =
|
|||||||
|
|
||||||
let record =
|
let record =
|
||||||
{
|
{
|
||||||
Name = Ident.Create name
|
Name = Ident.create name
|
||||||
Fields = fields
|
Fields = fields
|
||||||
Members = Some ([ constructor ; interfaceMembers ] @ extraInterfaces)
|
Members = Some ([ constructor ; interfaceMembers ] @ extraInterfaces)
|
||||||
XmlDoc = Some xmlDoc
|
XmlDoc = Some xmlDoc
|
||||||
@@ -314,7 +292,7 @@ module internal InterfaceMockGenerator =
|
|||||||
|
|
||||||
let private buildType (x : ParameterInfo) : SynType =
|
let private buildType (x : ParameterInfo) : SynType =
|
||||||
if x.IsOptional then
|
if x.IsOptional then
|
||||||
SynType.App (SynType.CreateLongIdent "option", Some range0, [ x.Type ], [], Some range0, false, range0)
|
SynType.app "option" [ x.Type ]
|
||||||
else
|
else
|
||||||
x.Type
|
x.Type
|
||||||
|
|
||||||
@@ -353,7 +331,7 @@ module internal InterfaceMockGenerator =
|
|||||||
=
|
=
|
||||||
let interfaceType = AstHelper.parseInterface interfaceType
|
let interfaceType = AstHelper.parseInterface interfaceType
|
||||||
let fields = interfaceType.Members |> List.map constructMember
|
let fields = interfaceType.Members |> List.map constructMember
|
||||||
let docString = PreXmlDoc.Create " Mock record type for an interface"
|
let docString = PreXmlDoc.create "Mock record type for an interface"
|
||||||
|
|
||||||
let name =
|
let name =
|
||||||
List.last interfaceType.Name
|
List.last interfaceType.Name
|
||||||
|
@@ -4,7 +4,6 @@ open System
|
|||||||
open System.Text
|
open System.Text
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
open Fantomas.FCS.Xml
|
|
||||||
open Myriad.Core
|
open Myriad.Core
|
||||||
|
|
||||||
type internal JsonParseOutputSpec =
|
type internal JsonParseOutputSpec =
|
||||||
@@ -30,30 +29,23 @@ module internal JsonParseGenerator =
|
|||||||
/// (match {indexed} with | null -> raise (System.Collections.Generic.KeyNotFoundException ()) | v -> v)
|
/// (match {indexed} with | null -> raise (System.Collections.Generic.KeyNotFoundException ()) | v -> v)
|
||||||
let assertNotNull (propertyName : SynExpr) (indexed : SynExpr) =
|
let assertNotNull (propertyName : SynExpr) (indexed : SynExpr) =
|
||||||
let raiseExpr =
|
let raiseExpr =
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateApp (
|
(SynExpr.createIdent "sprintf")
|
||||||
SynExpr.CreateIdentString "sprintf",
|
(SynExpr.CreateConst "Required key '%s' not found on JSON object")
|
||||||
SynExpr.CreateConstString "Required key '%s' not found on JSON object"
|
|> SynExpr.applyTo (SynExpr.paren propertyName)
|
||||||
),
|
|> SynExpr.paren
|
||||||
SynExpr.CreateParen propertyName
|
|
||||||
)
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|> SynExpr.applyFunction (
|
|> SynExpr.applyFunction (
|
||||||
SynExpr.CreateLongIdent (
|
SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ]
|
||||||
SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ]
|
|
||||||
)
|
)
|
||||||
)
|
|> SynExpr.paren
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "raise")
|
|
||||||
|
|
||||||
SynExpr.CreateMatch (
|
|
||||||
indexed,
|
|
||||||
[
|
[
|
||||||
SynMatchClause.Create (SynPat.CreateNull, None, raiseExpr)
|
SynMatchClause.create SynPat.createNull raiseExpr
|
||||||
SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, SynExpr.CreateIdentString "v")
|
SynMatchClause.create (SynPat.named "v") (SynExpr.createIdent "v")
|
||||||
]
|
]
|
||||||
)
|
|> SynExpr.createMatch indexed
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|
|
||||||
/// {node}.AsValue().GetValue<{typeName}> ()
|
/// {node}.AsValue().GetValue<{typeName}> ()
|
||||||
/// If `propertyName` is Some, uses `assertNotNull {node}` instead of `{node}`.
|
/// If `propertyName` is Some, uses `assertNotNull {node}` instead of `{node}`.
|
||||||
@@ -81,10 +73,8 @@ module internal JsonParseGenerator =
|
|||||||
|
|
||||||
/// {type}.jsonParse {node}
|
/// {type}.jsonParse {node}
|
||||||
let typeJsonParse (typeName : LongIdent) (node : SynExpr) : SynExpr =
|
let typeJsonParse (typeName : LongIdent) (node : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (typeName @ [ Ident.Create "jsonParse" ])),
|
|
||||||
node
|
node
|
||||||
)
|
|> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ Ident.create "jsonParse" ]))
|
||||||
|
|
||||||
/// collectionType is e.g. "List"; we'll be calling `ofSeq` on it.
|
/// collectionType is e.g. "List"; we'll be calling `ofSeq` on it.
|
||||||
/// body is the body of a lambda which takes a parameter `elt`.
|
/// body is the body of a lambda which takes a parameter `elt`.
|
||||||
@@ -103,51 +93,40 @@ module internal JsonParseGenerator =
|
|||||||
| Some propertyName -> assertNotNull propertyName node
|
| Some propertyName -> assertNotNull propertyName node
|
||||||
|> SynExpr.callMethod "AsArray"
|
|> SynExpr.callMethod "AsArray"
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction (SynExpr.createLongIdent [ "Seq" ; "map" ]) (SynExpr.createLambda "elt" body)
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
|
||||||
SynExpr.createLambda "elt" body
|
|
||||||
)
|
)
|
||||||
)
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ collectionType ; "ofSeq" ])
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ collectionType ; "ofSeq" ]))
|
|
||||||
|
|
||||||
/// match {node} with | null -> None | v -> {body} |> Some
|
/// match {node} with | null -> None | v -> {body} |> Some
|
||||||
/// Use the variable `v` to get access to the `Some`.
|
/// Use the variable `v` to get access to the `Some`.
|
||||||
let createParseLineOption (node : SynExpr) (body : SynExpr) : SynExpr =
|
let createParseLineOption (node : SynExpr) (body : SynExpr) : SynExpr =
|
||||||
let body = SynExpr.pipeThroughFunction (SynExpr.CreateIdentString "Some") body
|
let body = SynExpr.pipeThroughFunction (SynExpr.createIdent "Some") body
|
||||||
|
|
||||||
SynExpr.CreateMatch (
|
|
||||||
node,
|
|
||||||
[
|
[
|
||||||
SynMatchClause.Create (SynPat.CreateNull, None, SynExpr.CreateIdent (Ident.Create "None"))
|
SynMatchClause.create SynPat.createNull (SynExpr.createIdent "None")
|
||||||
SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, body)
|
SynMatchClause.create (SynPat.named "v") body
|
||||||
]
|
]
|
||||||
)
|
|> SynExpr.createMatch node
|
||||||
|
|
||||||
/// Given e.g. "float", returns "System.Double.Parse"
|
/// Given e.g. "float", returns "System.Double.Parse"
|
||||||
let parseFunction (typeName : string) : LongIdent =
|
let parseFunction (typeName : string) : LongIdent =
|
||||||
let qualified =
|
let qualified =
|
||||||
match AstHelper.qualifyPrimitiveType typeName with
|
match Primitives.qualifyType typeName with
|
||||||
| Some x -> x
|
| Some x -> x
|
||||||
| None -> failwith $"Could not recognise type %s{typeName} as a primitive."
|
| None -> failwith $"Could not recognise type %s{typeName} as a primitive."
|
||||||
|
|
||||||
List.append qualified [ Ident.Create "Parse" ]
|
List.append qualified [ Ident.create "Parse" ]
|
||||||
|
|
||||||
/// fun kvp -> let key = {key(kvp)} in let value = {value(kvp)} in (key, value))
|
/// fun kvp -> let key = {key(kvp)} in let value = {value(kvp)} in (key, value))
|
||||||
/// The inputs will be fed with appropriate SynExprs to apply them to the `kvp.Key` and `kvp.Value` args.
|
/// The inputs will be fed with appropriate SynExprs to apply them to the `kvp.Key` and `kvp.Value` args.
|
||||||
let dictionaryMapper (key : SynExpr -> SynExpr) (value : SynExpr -> SynExpr) : SynExpr =
|
let dictionaryMapper (key : SynExpr -> SynExpr) (value : SynExpr -> SynExpr) : SynExpr =
|
||||||
let keyArg = SynExpr.createLongIdent [ "kvp" ; "Key" ] |> SynExpr.CreateParen
|
let keyArg = SynExpr.createLongIdent [ "kvp" ; "Key" ] |> SynExpr.paren
|
||||||
|
|
||||||
let valueArg = SynExpr.createLongIdent [ "kvp" ; "Value" ] |> SynExpr.CreateParen
|
let valueArg = SynExpr.createLongIdent [ "kvp" ; "Value" ] |> SynExpr.paren
|
||||||
|
|
||||||
SynExpr.CreateTuple [ SynExpr.CreateIdentString "key" ; SynExpr.CreateIdentString "value" ]
|
SynExpr.CreateTuple [ SynExpr.createIdent "key" ; SynExpr.createIdent "value" ]
|
||||||
|> SynExpr.createLet
|
|> SynExpr.createLet [ SynBinding.Let (pattern = SynPat.named "value", expr = value valueArg) ]
|
||||||
[
|
|> SynExpr.createLet [ SynBinding.Let (pattern = SynPat.named "key", expr = key keyArg) ]
|
||||||
SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create "value"), expr = value valueArg)
|
|
||||||
]
|
|
||||||
|> SynExpr.createLet
|
|
||||||
[
|
|
||||||
SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create "key"), expr = key keyArg)
|
|
||||||
]
|
|
||||||
|> SynExpr.createLambda "kvp"
|
|> SynExpr.createLambda "kvp"
|
||||||
|
|
||||||
/// A conforming JSON object has only strings as keys. But it would be reasonable to allow the user
|
/// A conforming JSON object has only strings as keys. But it would be reasonable to allow the user
|
||||||
@@ -157,7 +136,7 @@ module internal JsonParseGenerator =
|
|||||||
| String -> key
|
| String -> key
|
||||||
| Uri ->
|
| Uri ->
|
||||||
key
|
key
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ]))
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Uri" ])
|
||||||
| _ ->
|
| _ ->
|
||||||
failwithf
|
failwithf
|
||||||
$"Unable to parse the key type %+A{desiredType} of a JSON object. Keys are strings, and this plugin does not know how to convert to that from a string."
|
$"Unable to parse the key type %+A{desiredType} of a JSON object. Keys are strings, and this plugin does not know how to convert to that from a string."
|
||||||
@@ -197,15 +176,8 @@ module internal JsonParseGenerator =
|
|||||||
| None -> basic
|
| None -> basic
|
||||||
| Some option ->
|
| Some option ->
|
||||||
let cond =
|
let cond =
|
||||||
SynExpr.DotGet (
|
SynExpr.DotGet (SynExpr.createIdent "exc", range0, SynLongIdent.createS "Message", range0)
|
||||||
SynExpr.CreateIdentString "exc",
|
|> SynExpr.callMethodArg "Contains" (SynExpr.CreateConst "cannot be converted to")
|
||||||
range0,
|
|
||||||
SynLongIdent.CreateString "Message",
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|> SynExpr.callMethodArg
|
|
||||||
"Contains"
|
|
||||||
(SynExpr.CreateConst (SynConst.CreateString "cannot be converted to"))
|
|
||||||
|
|
||||||
let handler =
|
let handler =
|
||||||
asValueGetValue propertyName "string" node
|
asValueGetValue propertyName "string" node
|
||||||
@@ -213,8 +185,7 @@ module internal JsonParseGenerator =
|
|||||||
|> SynExpr.ifThenElse
|
|> SynExpr.ifThenElse
|
||||||
(SynExpr.equals
|
(SynExpr.equals
|
||||||
option
|
option
|
||||||
(SynExpr.CreateLongIdent (
|
(SynExpr.createLongIdent
|
||||||
SynLongIdent.Create
|
|
||||||
[
|
[
|
||||||
"System"
|
"System"
|
||||||
"Text"
|
"Text"
|
||||||
@@ -222,82 +193,74 @@ module internal JsonParseGenerator =
|
|||||||
"Serialization"
|
"Serialization"
|
||||||
"JsonNumberHandling"
|
"JsonNumberHandling"
|
||||||
"AllowReadingFromString"
|
"AllowReadingFromString"
|
||||||
]
|
]))
|
||||||
)))
|
|
||||||
SynExpr.reraise
|
SynExpr.reraise
|
||||||
|> SynExpr.ifThenElse cond SynExpr.reraise
|
|> SynExpr.ifThenElse cond SynExpr.reraise
|
||||||
|
|
||||||
basic
|
basic
|
||||||
|> SynExpr.pipeThroughTryWith
|
|> SynExpr.pipeThroughTryWith
|
||||||
(SynPat.IsInst (
|
(SynPat.IsInst (
|
||||||
SynType.LongIdent (SynLongIdent.Create [ "System" ; "InvalidOperationException" ]),
|
SynType.LongIdent (SynLongIdent.createS' [ "System" ; "InvalidOperationException" ]),
|
||||||
range0
|
range0
|
||||||
))
|
))
|
||||||
handler
|
handler
|
||||||
| PrimitiveType typeName -> asValueGetValueIdent propertyName typeName node
|
| PrimitiveType typeName -> asValueGetValueIdent propertyName typeName node
|
||||||
| OptionType ty ->
|
| OptionType ty ->
|
||||||
parseNode None options ty (SynExpr.CreateIdentString "v")
|
parseNode None options ty (SynExpr.createIdent "v")
|
||||||
|> createParseLineOption node
|
|> createParseLineOption node
|
||||||
| ListType ty ->
|
| ListType ty ->
|
||||||
parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"))
|
parseNode None options ty (SynExpr.createIdent "elt")
|
||||||
|> asArrayMapped propertyName "List" node
|
|> asArrayMapped propertyName "List" node
|
||||||
| ArrayType ty ->
|
| ArrayType ty ->
|
||||||
parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"))
|
parseNode None options ty (SynExpr.createIdent "elt")
|
||||||
|> asArrayMapped propertyName "Array" node
|
|> asArrayMapped propertyName "Array" node
|
||||||
| IDictionaryType (keyType, valueType) ->
|
| IDictionaryType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
)
|
||||||
)
|
|> SynExpr.pipeThroughFunction (SynExpr.createIdent "dict")
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "dict" ]))
|
|
||||||
| DictionaryType (keyType, valueType) ->
|
| DictionaryType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
SynExpr.CreateLongIdent (
|
(SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ])
|
||||||
SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "Dictionary" ])
|
SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "Dictionary" ]
|
||||||
)
|
)
|
||||||
| IReadOnlyDictionaryType (keyType, valueType) ->
|
| IReadOnlyDictionaryType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
)
|
||||||
)
|
|> SynExpr.pipeThroughFunction (SynExpr.createIdent "readOnlyDict")
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "readOnlyDict" ]))
|
|
||||||
| MapType (keyType, valueType) ->
|
| MapType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
)
|
||||||
)
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "Map" ; "ofSeq" ])
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Map" ; "ofSeq" ]))
|
|
||||||
| BigInt ->
|
| BigInt ->
|
||||||
node
|
node
|
||||||
|> SynExpr.callMethod "ToJsonString"
|
|> SynExpr.callMethod "ToJsonString"
|
||||||
|> SynExpr.CreateParen
|
|> SynExpr.paren
|
||||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "Numerics" ; "BigInteger" ; "Parse" ])
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "Numerics" ; "BigInteger" ; "Parse" ])
|
||||||
| _ ->
|
| _ ->
|
||||||
// Let's just hope that we've also got our own type annotation!
|
// Let's just hope that we've also got our own type annotation!
|
||||||
@@ -314,7 +277,7 @@ module internal JsonParseGenerator =
|
|||||||
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
||||||
/// The result of this function is the body of a let-binding (not including the LHS of that let-binding).
|
/// The result of this function is the body of a let-binding (not including the LHS of that let-binding).
|
||||||
let createParseRhs (options : JsonParseOption) (propertyName : SynExpr) (fieldType : SynType) : SynExpr =
|
let createParseRhs (options : JsonParseOption) (propertyName : SynExpr) (fieldType : SynType) : SynExpr =
|
||||||
let objectToParse = SynExpr.CreateIdentString "node" |> SynExpr.index propertyName
|
let objectToParse = SynExpr.createIdent "node" |> SynExpr.index propertyName
|
||||||
parseNode (Some propertyName) options fieldType objectToParse
|
parseNode (Some propertyName) options fieldType objectToParse
|
||||||
|
|
||||||
let isJsonNumberHandling (literal : LongIdent) : bool =
|
let isJsonNumberHandling (literal : LongIdent) : bool =
|
||||||
@@ -331,45 +294,36 @@ module internal JsonParseGenerator =
|
|||||||
/// That is, we give you access to a `JsonNode` called `node`,
|
/// That is, we give you access to a `JsonNode` called `node`,
|
||||||
/// and you must return a `typeName`.
|
/// and you must return a `typeName`.
|
||||||
let scaffolding (spec : JsonParseOutputSpec) (typeName : LongIdent) (functionBody : SynExpr) : SynModuleDecl =
|
let scaffolding (spec : JsonParseOutputSpec) (typeName : LongIdent) (functionBody : SynExpr) : SynModuleDecl =
|
||||||
let xmlDoc = PreXmlDoc.Create " Parse from a JSON node."
|
let xmlDoc = PreXmlDoc.create "Parse from a JSON node."
|
||||||
|
|
||||||
let returnInfo = SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName)
|
let returnInfo = SynType.createLongIdent typeName
|
||||||
|
|
||||||
let inputArg = Ident.Create "node"
|
let inputArg = "node"
|
||||||
let functionName = Ident.Create "jsonParse"
|
let functionName = Ident.create "jsonParse"
|
||||||
|
|
||||||
let arg =
|
let arg =
|
||||||
SynPat.CreateNamed inputArg
|
SynPat.named inputArg
|
||||||
|> SynPat.annotateType (
|
|> SynPat.annotateType (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||||
SynType.LongIdent (SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
|
||||||
)
|
|
||||||
|
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
let binding =
|
let binding =
|
||||||
SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ arg ] functionBody
|
SynBinding.basic [ functionName ] [ arg ] functionBody
|
||||||
|> SynBinding.makeStaticMember
|
|
||||||
|> SynBinding.withXmlDoc xmlDoc
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|> SynBinding.withReturnAnnotation returnInfo
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|
|> SynMemberDefn.staticMember
|
||||||
|
|
||||||
let mem = SynMemberDefn.Member (binding, range0)
|
let componentInfo =
|
||||||
|
SynComponentInfo.createLong typeName
|
||||||
|
|> SynComponentInfo.withDocString (PreXmlDoc.create "Extension methods for JSON parsing")
|
||||||
|
|
||||||
let containingType =
|
let containingType =
|
||||||
SynTypeDefn.SynTypeDefn (
|
SynTypeDefnRepr.augmentation ()
|
||||||
SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"),
|
|> SynTypeDefn.create componentInfo
|
||||||
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0),
|
|> SynTypeDefn.withMemberDefns [ binding ]
|
||||||
[ mem ],
|
|
||||||
None,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
|
||||||
EqualsRange = None
|
|
||||||
WithKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
SynModuleDecl.Types ([ containingType ], range0)
|
SynModuleDecl.Types ([ containingType ], range0)
|
||||||
else
|
else
|
||||||
SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ arg ] functionBody
|
SynBinding.basic [ functionName ] [ arg ] functionBody
|
||||||
|> SynBinding.withXmlDoc xmlDoc
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|> SynBinding.withReturnAnnotation returnInfo
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
@@ -378,7 +332,10 @@ module internal JsonParseGenerator =
|
|||||||
let getParseOptions (fieldAttrs : SynAttribute list) =
|
let getParseOptions (fieldAttrs : SynAttribute list) =
|
||||||
(JsonParseOption.None, fieldAttrs)
|
(JsonParseOption.None, fieldAttrs)
|
||||||
||> List.fold (fun options attr ->
|
||> List.fold (fun options attr ->
|
||||||
if attr.TypeName.AsString.EndsWith ("JsonNumberHandling", StringComparison.Ordinal) then
|
if
|
||||||
|
(SynLongIdent.toString attr.TypeName)
|
||||||
|
.EndsWith ("JsonNumberHandling", StringComparison.Ordinal)
|
||||||
|
then
|
||||||
let qualifiedEnumValue =
|
let qualifiedEnumValue =
|
||||||
match SynExpr.stripOptionalParen attr.ArgExpr with
|
match SynExpr.stripOptionalParen attr.ArgExpr with
|
||||||
| SynExpr.LongIdent (_, SynLongIdent (ident, _, _), _, _) when isJsonNumberHandling ident ->
|
| SynExpr.LongIdent (_, SynLongIdent (ident, _, _), _, _) when isJsonNumberHandling ident ->
|
||||||
@@ -401,15 +358,15 @@ module internal JsonParseGenerator =
|
|||||||
options
|
options
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let createRecordMaker (spec : JsonParseOutputSpec) (fields : SynFieldData<Ident> list) =
|
||||||
let createRecordMaker (spec : JsonParseOutputSpec) (typeName : LongIdent) (fields : SynFieldData<Ident> list) =
|
|
||||||
let assignments =
|
let assignments =
|
||||||
fields
|
fields
|
||||||
|> List.mapi (fun i fieldData ->
|
|> List.mapi (fun i fieldData ->
|
||||||
let propertyNameAttr =
|
let propertyNameAttr =
|
||||||
fieldData.Attrs
|
fieldData.Attrs
|
||||||
|> List.tryFind (fun attr ->
|
|> List.tryFind (fun attr ->
|
||||||
attr.TypeName.AsString.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
(SynLongIdent.toString attr.TypeName)
|
||||||
|
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||||
)
|
)
|
||||||
|
|
||||||
let options = getParseOptions fieldData.Attrs
|
let options = getParseOptions fieldData.Attrs
|
||||||
@@ -425,18 +382,17 @@ module internal JsonParseGenerator =
|
|||||||
if fieldData.Ident.idText.Length > 1 then
|
if fieldData.Ident.idText.Length > 1 then
|
||||||
sb.Append (fieldData.Ident.idText.Substring 1) |> ignore<StringBuilder>
|
sb.Append (fieldData.Ident.idText.Substring 1) |> ignore<StringBuilder>
|
||||||
|
|
||||||
sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst
|
sb.ToString () |> SynExpr.CreateConst
|
||||||
| Some name -> name.ArgExpr
|
| Some name -> name.ArgExpr
|
||||||
|
|
||||||
createParseRhs options propertyName fieldData.Type
|
createParseRhs options propertyName fieldData.Type
|
||||||
|> SynBinding.basic (SynLongIdent.CreateString $"arg_%i{i}") []
|
|> SynBinding.basic [ Ident.create $"arg_%i{i}" ] []
|
||||||
)
|
)
|
||||||
|
|
||||||
let finalConstruction =
|
let finalConstruction =
|
||||||
fields
|
fields
|
||||||
|> List.mapi (fun i fieldData ->
|
|> List.mapi (fun i fieldData ->
|
||||||
(SynLongIdent.CreateFromLongIdent [ fieldData.Ident ], true),
|
(SynLongIdent.createI fieldData.Ident, true), Some (SynExpr.createIdent $"arg_%i{i}")
|
||||||
Some (SynExpr.CreateLongIdent (SynLongIdent.CreateString $"arg_%i{i}"))
|
|
||||||
)
|
)
|
||||||
|> AstHelper.instantiateRecord
|
|> AstHelper.instantiateRecord
|
||||||
|
|
||||||
@@ -458,13 +414,13 @@ module internal JsonParseGenerator =
|
|||||||
let options = getParseOptions field.Attrs
|
let options = getParseOptions field.Attrs
|
||||||
createParseRhs options propertyName field.Type
|
createParseRhs options propertyName field.Type
|
||||||
)
|
)
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tuple
|
||||||
|> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ case.Ident ]))
|
|> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ case.Ident ]))
|
||||||
|> SynExpr.createLet
|
|> SynExpr.createLet
|
||||||
[
|
[
|
||||||
SynExpr.index (SynExpr.CreateConstString "data") (SynExpr.CreateIdentString "node")
|
SynExpr.index (SynExpr.CreateConst "data") (SynExpr.createIdent "node")
|
||||||
|> assertNotNull (SynExpr.CreateConstString "data")
|
|> assertNotNull (SynExpr.CreateConst "data")
|
||||||
|> SynBinding.basic (SynLongIdent.CreateString "node") []
|
|> SynBinding.basic [ Ident.create "node" ] []
|
||||||
]
|
]
|
||||||
|
|
||||||
match propertyName with
|
match propertyName with
|
||||||
@@ -481,30 +437,19 @@ module internal JsonParseGenerator =
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
| _ ->
|
| _ ->
|
||||||
SynMatchClause.SynMatchClause (
|
SynMatchClause.create (SynPat.named "x") body
|
||||||
SynPat.CreateNamed (Ident.Create "x"),
|
|> SynMatchClause.withWhere (SynExpr.equals (SynExpr.createIdent "x") propertyName)
|
||||||
Some (SynExpr.equals (SynExpr.CreateIdentString "x") propertyName),
|
|
||||||
body,
|
|
||||||
range0,
|
|
||||||
DebugPointAtTarget.Yes,
|
|
||||||
{
|
|
||||||
ArrowRange = Some range0
|
|
||||||
BarRange = Some range0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> fun l ->
|
|> fun l ->
|
||||||
l
|
l
|
||||||
@ [
|
@ [
|
||||||
let fail =
|
let fail =
|
||||||
SynExpr.plus
|
SynExpr.plus (SynExpr.CreateConst "Unrecognised 'type' field value: ") (SynExpr.createIdent "v")
|
||||||
(SynExpr.CreateConstString "Unrecognised 'type' field value: ")
|
|> SynExpr.paren
|
||||||
(SynExpr.CreateIdentString "v")
|
|> SynExpr.applyFunction (SynExpr.createIdent "failwith")
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "failwith")
|
|
||||||
|
|
||||||
SynMatchClause.SynMatchClause (
|
SynMatchClause.SynMatchClause (
|
||||||
SynPat.CreateNamed (Ident.Create "v"),
|
SynPat.named "v",
|
||||||
None,
|
None,
|
||||||
fail,
|
fail,
|
||||||
range0,
|
range0,
|
||||||
@@ -515,34 +460,21 @@ module internal JsonParseGenerator =
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|> SynExpr.createMatch (SynExpr.CreateIdentString "ty")
|
|> SynExpr.createMatch (SynExpr.createIdent "ty")
|
||||||
|> SynExpr.createLet
|
|> SynExpr.createLet
|
||||||
[
|
[
|
||||||
let property = SynExpr.CreateConstString "type"
|
let property = SynExpr.CreateConst "type"
|
||||||
|
|
||||||
SynExpr.CreateIdentString "node"
|
SynExpr.createIdent "node"
|
||||||
|> SynExpr.index property
|
|> SynExpr.index property
|
||||||
|> assertNotNull property
|
|> assertNotNull property
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.createLambda
|
SynExpr.createLambda
|
||||||
"v"
|
"v"
|
||||||
(SynExpr.callGenericMethod "GetValue" [ Ident.Create "string" ] (SynExpr.CreateIdentString "v"))
|
(SynExpr.callGenericMethod "GetValue" [ Ident.create "string" ] (SynExpr.createIdent "v"))
|
||||||
)
|
)
|
||||||
|> SynBinding.basic (SynLongIdent.CreateString "ty") []
|
|> SynBinding.basic [ Ident.create "ty" ] []
|
||||||
]
|
]
|
||||||
(*
|
|
||||||
let ty =
|
|
||||||
match node.["type"] with
|
|
||||||
| null -> raise (System.Collections.Generic.KeyNotFoundException ())
|
|
||||||
| v -> v.GetValue<string> ()
|
|
||||||
match ty with
|
|
||||||
| "emptyCase" -> FirstDu.EmptyCase
|
|
||||||
| "case1" ->
|
|
||||||
FirstDu.Case1
|
|
||||||
| "case2" -> FirstDu.Case2
|
|
||||||
| _ -> failwithf "Unrecognised case name: %s" ty
|
|
||||||
*)
|
|
||||||
|
|
||||||
|
|
||||||
let createModule (namespaceId : LongIdent) (spec : JsonParseOutputSpec) (typeDefn : SynTypeDefn) =
|
let createModule (namespaceId : LongIdent) (spec : JsonParseOutputSpec) (typeDefn : SynTypeDefn) =
|
||||||
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||||
@@ -553,12 +485,9 @@ module internal JsonParseGenerator =
|
|||||||
|
|
||||||
let attributes =
|
let attributes =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
[ SynAttribute.autoOpen ]
|
||||||
else
|
else
|
||||||
[
|
[ SynAttribute.requireQualifiedAccess ; SynAttribute.compilationRepresentation ]
|
||||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
|
||||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
|
||||||
]
|
|
||||||
|
|
||||||
let xmlDoc =
|
let xmlDoc =
|
||||||
let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "."
|
let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "."
|
||||||
@@ -570,7 +499,7 @@ module internal JsonParseGenerator =
|
|||||||
"methods"
|
"methods"
|
||||||
|
|
||||||
$"Module containing JSON parsing %s{description} for the %s{fullyQualified} type"
|
$"Module containing JSON parsing %s{description} for the %s{fullyQualified} type"
|
||||||
|> PreXmlDoc.Create
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let moduleName =
|
let moduleName =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
@@ -581,32 +510,31 @@ module internal JsonParseGenerator =
|
|||||||
List.last ident
|
List.last ident
|
||||||
|> fun i -> i.idText
|
|> fun i -> i.idText
|
||||||
|> fun s -> s + "JsonParseExtension"
|
|> fun s -> s + "JsonParseExtension"
|
||||||
|> Ident.Create
|
|> Ident.create
|
||||||
|
|
||||||
List.take (List.length ident - 1) ident @ [ expanded ]
|
List.take (List.length ident - 1) ident @ [ expanded ]
|
||||||
else
|
else
|
||||||
ident
|
ident
|
||||||
|
|
||||||
let info =
|
let info =
|
||||||
SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc)
|
SynComponentInfo.createLong moduleName
|
||||||
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
|
|> SynComponentInfo.addAttributes attributes
|
||||||
|
|
||||||
let decl =
|
let decl =
|
||||||
match synTypeDefnRepr with
|
match synTypeDefnRepr with
|
||||||
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, fields, _range), _) ->
|
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, fields, _range), _) ->
|
||||||
let fields = fields |> List.map SynField.extractWithIdent
|
fields |> List.map SynField.extractWithIdent |> createRecordMaker spec
|
||||||
createRecordMaker spec ident fields
|
|
||||||
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (_accessibility, cases, _range), _) ->
|
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (_accessibility, cases, _range), _) ->
|
||||||
let optionGet (i : Ident option) =
|
let optionGet (i : Ident option) =
|
||||||
match i with
|
match i with
|
||||||
| None -> failwith "WoofWare.Myriad requires union cases to have identifiers on each field."
|
| None -> failwith "WoofWare.Myriad requires union cases to have identifiers on each field."
|
||||||
| Some i -> i
|
| Some i -> i
|
||||||
|
|
||||||
let cases =
|
|
||||||
cases
|
cases
|
||||||
|> List.map SynUnionCase.extract
|
|> List.map SynUnionCase.extract
|
||||||
|> List.map (UnionCase.mapIdentFields optionGet)
|
|> List.map (UnionCase.mapIdentFields optionGet)
|
||||||
|
|> createUnionMaker spec ident
|
||||||
createUnionMaker spec ident cases
|
|
||||||
| _ -> failwithf "Not a record or union type"
|
| _ -> failwithf "Not a record or union type"
|
||||||
|
|
||||||
let mdl =
|
let mdl =
|
||||||
|
@@ -3,8 +3,6 @@ namespace WoofWare.Myriad.Plugins
|
|||||||
open System
|
open System
|
||||||
open System.Text
|
open System.Text
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Fantomas.FCS.Xml
|
|
||||||
open Myriad.Core
|
open Myriad.Core
|
||||||
|
|
||||||
type internal JsonSerializeOutputSpec =
|
type internal JsonSerializeOutputSpec =
|
||||||
@@ -40,37 +38,24 @@ module internal JsonSerializeGenerator =
|
|||||||
)
|
)
|
||||||
| OptionType ty ->
|
| OptionType ty ->
|
||||||
// fun field -> match field with | None -> JsonValue.Create null | Some v -> {serializeNode ty} field
|
// fun field -> match field with | None -> JsonValue.Create null | Some v -> {serializeNode ty} field
|
||||||
[
|
let noneClause =
|
||||||
SynMatchClause.Create (
|
|
||||||
SynPat.CreateLongIdent (SynLongIdent.CreateString "None", []),
|
|
||||||
None,
|
|
||||||
// The absolutely galaxy-brained implementation of JsonValue has `JsonValue.Parse "null"`
|
// The absolutely galaxy-brained implementation of JsonValue has `JsonValue.Parse "null"`
|
||||||
// identically equal to null. We have to work around this later, but we might as well just
|
// identically equal to null. We have to work around this later, but we might as well just
|
||||||
// be efficient here and whip up the null directly.
|
// be efficient here and whip up the null directly.
|
||||||
SynExpr.CreateNull
|
SynExpr.createNull ()
|
||||||
|> SynExpr.upcast' (
|
|> SynExpr.upcast' (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||||
SynType.CreateLongIdent (
|
|> SynMatchClause.create (SynPat.named "None")
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
|
||||||
)
|
let someClause =
|
||||||
)
|
SynExpr.applyFunction (serializeNode ty) (SynExpr.createIdent "field")
|
||||||
|
|> SynExpr.paren
|
||||||
|
|> SynExpr.upcast' (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||||
|
|> SynMatchClause.create (
|
||||||
|
SynPat.CreateLongIdent (SynLongIdent.createS "Some", [ SynPat.named "field" ])
|
||||||
)
|
)
|
||||||
|
|
||||||
SynMatchClause.Create (
|
[ noneClause ; someClause ]
|
||||||
SynPat.CreateLongIdent (
|
|> SynExpr.createMatch (SynExpr.createIdent "field")
|
||||||
SynLongIdent.CreateString "Some",
|
|
||||||
[ SynPat.CreateNamed (Ident.Create "field") ]
|
|
||||||
),
|
|
||||||
None,
|
|
||||||
SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "field")
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|> SynExpr.upcast' (
|
|
||||||
SynType.CreateLongIdent (
|
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|> SynExpr.createMatch (SynExpr.CreateIdentString "field")
|
|
||||||
|> SynExpr.createLambda "field"
|
|> SynExpr.createLambda "field"
|
||||||
| ArrayType ty
|
| ArrayType ty
|
||||||
| ListType ty ->
|
| ListType ty ->
|
||||||
@@ -84,22 +69,21 @@ module internal JsonSerializeGenerator =
|
|||||||
DebugPointAtInOrTo.Yes range0,
|
DebugPointAtInOrTo.Yes range0,
|
||||||
SeqExprOnly.SeqExprOnly false,
|
SeqExprOnly.SeqExprOnly false,
|
||||||
true,
|
true,
|
||||||
SynPat.CreateNamed (Ident.Create "mem"),
|
SynPat.named "mem",
|
||||||
SynExpr.CreateIdent (Ident.Create "field"),
|
SynExpr.createIdent "field",
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "arr" ; "Add" ]),
|
(SynExpr.createLongIdent [ "arr" ; "Add" ])
|
||||||
SynExpr.CreateParen (SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "mem"))
|
(SynExpr.paren (SynExpr.applyFunction (serializeNode ty) (SynExpr.createIdent "mem"))),
|
||||||
),
|
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
SynExpr.CreateIdentString "arr"
|
SynExpr.createIdent "arr"
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateSequential
|
|> SynExpr.sequential
|
||||||
|> SynExpr.createLet
|
|> SynExpr.createLet
|
||||||
[
|
[
|
||||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonArray" ]
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonArray" ]
|
||||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
|> SynBinding.basic (SynLongIdent.CreateString "arr") []
|
|> SynBinding.basic [ Ident.create "arr" ] []
|
||||||
]
|
]
|
||||||
|> SynExpr.createLambda "field"
|
|> SynExpr.createLambda "field"
|
||||||
| IDictionaryType (_keyType, valueType)
|
| IDictionaryType (_keyType, valueType)
|
||||||
@@ -117,46 +101,31 @@ module internal JsonSerializeGenerator =
|
|||||||
DebugPointAtInOrTo.Yes range0,
|
DebugPointAtInOrTo.Yes range0,
|
||||||
SeqExprOnly.SeqExprOnly false,
|
SeqExprOnly.SeqExprOnly false,
|
||||||
true,
|
true,
|
||||||
SynPat.CreateParen (
|
SynPat.paren (
|
||||||
SynPat.CreateLongIdent (
|
SynPat.CreateLongIdent (
|
||||||
SynLongIdent.CreateString "KeyValue",
|
SynLongIdent.createS "KeyValue",
|
||||||
[
|
[ SynPat.tuple [ SynPat.named "key" ; SynPat.named "value" ] ]
|
||||||
SynPat.CreateParen (
|
|
||||||
SynPat.Tuple (
|
|
||||||
false,
|
|
||||||
[
|
|
||||||
SynPat.CreateNamed (Ident.Create "key")
|
|
||||||
SynPat.CreateNamed (Ident.Create "value")
|
|
||||||
],
|
|
||||||
[ range0 ],
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
SynExpr.CreateIdent (Ident.Create "field"),
|
SynExpr.createIdent "field",
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent [ "ret" ; "Add" ],
|
(SynExpr.createLongIdent [ "ret" ; "Add" ])
|
||||||
SynExpr.CreateParenedTuple
|
(SynExpr.tuple
|
||||||
[
|
[
|
||||||
SynExpr.CreateApp (
|
SynExpr.createLongIdent [ "key" ; "ToString" ]
|
||||||
SynExpr.createLongIdent [ "key" ; "ToString" ],
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
SynExpr.CreateConst SynConst.Unit
|
SynExpr.applyFunction (serializeNode valueType) (SynExpr.createIdent "value")
|
||||||
)
|
]),
|
||||||
SynExpr.CreateApp (serializeNode valueType, SynExpr.CreateIdentString "value")
|
|
||||||
]
|
|
||||||
),
|
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
SynExpr.CreateIdentString "ret"
|
SynExpr.createIdent "ret"
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateSequential
|
|> SynExpr.sequential
|
||||||
|> SynExpr.createLet
|
|> SynExpr.createLet
|
||||||
[
|
[
|
||||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
|> SynBinding.basic (SynLongIdent.CreateString "ret") []
|
|> SynBinding.basic [ Ident.create "ret" ] []
|
||||||
]
|
]
|
||||||
|> SynExpr.createLambda "field"
|
|> SynExpr.createLambda "field"
|
||||||
| _ ->
|
| _ ->
|
||||||
@@ -166,22 +135,27 @@ module internal JsonSerializeGenerator =
|
|||||||
| SynType.LongIdent ident -> ident.LongIdent
|
| SynType.LongIdent ident -> ident.LongIdent
|
||||||
| _ -> failwith $"Unrecognised type: %+A{fieldType}"
|
| _ -> failwith $"Unrecognised type: %+A{fieldType}"
|
||||||
|
|
||||||
SynExpr.createLongIdent' (typeName @ [ Ident.Create "toJsonNode" ])
|
SynExpr.createLongIdent' (typeName @ [ Ident.create "toJsonNode" ])
|
||||||
|
|
||||||
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
||||||
/// `node.Add ({propertyName}, {toJsonNode})`
|
/// `node.Add ({propertyName}, {toJsonNode})`
|
||||||
let createSerializeRhsRecord (propertyName : SynExpr) (fieldId : Ident) (fieldType : SynType) : SynExpr =
|
let createSerializeRhsRecord (propertyName : SynExpr) (fieldId : Ident) (fieldType : SynType) : SynExpr =
|
||||||
[
|
[
|
||||||
propertyName
|
propertyName
|
||||||
SynExpr.CreateApp (serializeNode fieldType, SynExpr.createLongIdent' [ Ident.Create "input" ; fieldId ])
|
SynExpr.applyFunction
|
||||||
|
(serializeNode fieldType)
|
||||||
|
(SynExpr.createLongIdent' [ Ident.create "input" ; fieldId ])
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tuple
|
||||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||||
|
|
||||||
let getPropertyName (fieldId : Ident) (attrs : SynAttribute list) : SynExpr =
|
let getPropertyName (fieldId : Ident) (attrs : SynAttribute list) : SynExpr =
|
||||||
let propertyNameAttr =
|
let propertyNameAttr =
|
||||||
attrs
|
attrs
|
||||||
|> List.tryFind (fun attr -> attr.TypeName.AsString.EndsWith ("JsonPropertyName", StringComparison.Ordinal))
|
|> List.tryFind (fun attr ->
|
||||||
|
(SynLongIdent.toString attr.TypeName)
|
||||||
|
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||||
|
)
|
||||||
|
|
||||||
match propertyNameAttr with
|
match propertyNameAttr with
|
||||||
| None ->
|
| None ->
|
||||||
@@ -191,7 +165,7 @@ module internal JsonSerializeGenerator =
|
|||||||
if fieldId.idText.Length > 1 then
|
if fieldId.idText.Length > 1 then
|
||||||
sb.Append fieldId.idText.[1..] |> ignore
|
sb.Append fieldId.idText.[1..] |> ignore
|
||||||
|
|
||||||
sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst
|
sb.ToString () |> SynExpr.CreateConst
|
||||||
| Some name -> name.ArgExpr
|
| Some name -> name.ArgExpr
|
||||||
|
|
||||||
/// `populateNode` will be inserted before we return the `node` variable.
|
/// `populateNode` will be inserted before we return the `node` variable.
|
||||||
@@ -207,67 +181,60 @@ module internal JsonSerializeGenerator =
|
|||||||
(populateNode : SynExpr)
|
(populateNode : SynExpr)
|
||||||
: SynModuleDecl
|
: SynModuleDecl
|
||||||
=
|
=
|
||||||
let xmlDoc = PreXmlDoc.Create " Serialize to a JSON node"
|
let xmlDoc = PreXmlDoc.create "Serialize to a JSON node"
|
||||||
|
|
||||||
let returnInfo =
|
let returnInfo =
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
SynLongIdent.createS' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||||
|> SynType.LongIdent
|
|> SynType.LongIdent
|
||||||
|
|
||||||
let functionName = Ident.Create "toJsonNode"
|
let functionName = Ident.create "toJsonNode"
|
||||||
|
|
||||||
let assignments =
|
let assignments =
|
||||||
[
|
[
|
||||||
populateNode
|
populateNode
|
||||||
SynExpr.Upcast (SynExpr.CreateIdentString "node", SynType.Anon range0, range0)
|
SynExpr.Upcast (SynExpr.createIdent "node", SynType.Anon range0, range0)
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateSequential
|
|> SynExpr.sequential
|
||||||
|> SynExpr.createLet
|
|> SynExpr.createLet
|
||||||
[
|
[
|
||||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
|> SynBinding.basic (SynLongIdent.CreateString "node") []
|
|> SynBinding.basic [ Ident.create "node" ] []
|
||||||
]
|
]
|
||||||
|
|
||||||
let pattern =
|
let pattern =
|
||||||
SynPat.CreateNamed inputArgName
|
SynPat.CreateNamed inputArgName
|
||||||
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName))
|
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create typeName))
|
||||||
|
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
let binding =
|
let componentInfo =
|
||||||
|
SynComponentInfo.createLong typeName
|
||||||
|
|> SynComponentInfo.withDocString (PreXmlDoc.create "Extension methods for JSON parsing")
|
||||||
|
|
||||||
|
let memberDef =
|
||||||
assignments
|
assignments
|
||||||
|> SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ pattern ]
|
|> SynBinding.basic [ functionName ] [ pattern ]
|
||||||
|> SynBinding.withXmlDoc xmlDoc
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|> SynBinding.withReturnAnnotation returnInfo
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|> SynBinding.makeStaticMember
|
|> SynMemberDefn.staticMember
|
||||||
|
|
||||||
let mem = SynMemberDefn.Member (binding, range0)
|
|
||||||
|
|
||||||
let containingType =
|
let containingType =
|
||||||
SynTypeDefn.SynTypeDefn (
|
SynTypeDefnRepr.augmentation ()
|
||||||
SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"),
|
|> SynTypeDefn.create componentInfo
|
||||||
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0),
|
|> SynTypeDefn.withMemberDefns [ memberDef ]
|
||||||
[ mem ],
|
|
||||||
None,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
|
||||||
EqualsRange = None
|
|
||||||
WithKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
SynModuleDecl.Types ([ containingType ], range0)
|
SynModuleDecl.Types ([ containingType ], range0)
|
||||||
else
|
else
|
||||||
let binding =
|
let binding =
|
||||||
assignments
|
assignments
|
||||||
|> SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ pattern ]
|
|> SynBinding.basic [ functionName ] [ pattern ]
|
||||||
|> SynBinding.withReturnAnnotation returnInfo
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|> SynBinding.withXmlDoc xmlDoc
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|
|
||||||
SynModuleDecl.CreateLet [ binding ]
|
SynModuleDecl.CreateLet [ binding ]
|
||||||
|
|
||||||
let recordModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (fields : SynField list) =
|
let recordModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (fields : SynField list) =
|
||||||
let inputArg = Ident.Create "input"
|
let inputArg = Ident.create "input"
|
||||||
let fields = fields |> List.map SynField.extractWithIdent
|
let fields = fields |> List.map SynField.extractWithIdent
|
||||||
|
|
||||||
fields
|
fields
|
||||||
@@ -275,25 +242,25 @@ module internal JsonSerializeGenerator =
|
|||||||
let propertyName = getPropertyName fieldData.Ident fieldData.Attrs
|
let propertyName = getPropertyName fieldData.Ident fieldData.Attrs
|
||||||
createSerializeRhsRecord propertyName fieldData.Ident fieldData.Type
|
createSerializeRhsRecord propertyName fieldData.Ident fieldData.Type
|
||||||
)
|
)
|
||||||
|> SynExpr.CreateSequential
|
|> SynExpr.sequential
|
||||||
|> fun expr -> SynExpr.Do (expr, range0)
|
|> fun expr -> SynExpr.Do (expr, range0)
|
||||||
|> scaffolding spec typeName inputArg
|
|> scaffolding spec typeName inputArg
|
||||||
|
|
||||||
let unionModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (cases : SynUnionCase list) =
|
let unionModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (cases : SynUnionCase list) =
|
||||||
let inputArg = Ident.Create "input"
|
let inputArg = Ident.create "input"
|
||||||
let fields = cases |> List.map SynUnionCase.extract
|
let fields = cases |> List.map SynUnionCase.extract
|
||||||
|
|
||||||
fields
|
fields
|
||||||
|> List.map (fun unionCase ->
|
|> List.map (fun unionCase ->
|
||||||
let propertyName = getPropertyName unionCase.Ident unionCase.Attrs
|
let propertyName = getPropertyName unionCase.Ident unionCase.Attrs
|
||||||
|
|
||||||
let caseNames = unionCase.Fields |> List.mapi (fun i _ -> Ident.Create $"arg%i{i}")
|
let caseNames = unionCase.Fields |> List.mapi (fun i _ -> Ident.create $"arg%i{i}")
|
||||||
|
|
||||||
let argPats = SynArgPats.create caseNames
|
let argPats = SynArgPats.create caseNames
|
||||||
|
|
||||||
let pattern =
|
let pattern =
|
||||||
SynPat.LongIdent (
|
SynPat.LongIdent (
|
||||||
SynLongIdent.CreateFromLongIdent (typeName @ [ unionCase.Ident ]),
|
SynLongIdent.create (typeName @ [ unionCase.Ident ]),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
argPats,
|
argPats,
|
||||||
@@ -303,25 +270,21 @@ module internal JsonSerializeGenerator =
|
|||||||
|
|
||||||
let typeLine =
|
let typeLine =
|
||||||
[
|
[
|
||||||
SynExpr.CreateConstString "type"
|
SynExpr.CreateConst "type"
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ],
|
(SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ])
|
||||||
propertyName
|
propertyName
|
||||||
)
|
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tuple
|
||||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||||
|
|
||||||
let dataNode =
|
let dataNode =
|
||||||
SynBinding.Let (
|
SynBinding.Let (
|
||||||
pattern = SynPat.CreateNamed (Ident.Create "dataNode"),
|
pattern = SynPat.named "dataNode",
|
||||||
expr =
|
expr =
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (
|
(SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ])
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
(SynExpr.CreateConst ())
|
||||||
),
|
|
||||||
SynExpr.CreateConst SynConst.Unit
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let dataBindings =
|
let dataBindings =
|
||||||
@@ -331,20 +294,20 @@ module internal JsonSerializeGenerator =
|
|||||||
let propertyName = getPropertyName (Option.get fieldData.Ident) fieldData.Attrs
|
let propertyName = getPropertyName (Option.get fieldData.Ident) fieldData.Attrs
|
||||||
|
|
||||||
let node =
|
let node =
|
||||||
SynExpr.CreateApp (serializeNode fieldData.Type, SynExpr.CreateIdent caseName)
|
SynExpr.applyFunction (serializeNode fieldData.Type) (SynExpr.createIdent' caseName)
|
||||||
|
|
||||||
[ propertyName ; node ]
|
[ propertyName ; node ]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tuple
|
||||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "dataNode" ; "Add" ])
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "dataNode" ; "Add" ])
|
||||||
)
|
)
|
||||||
|
|
||||||
let assignToNode =
|
let assignToNode =
|
||||||
[ SynExpr.CreateConstString "data" ; SynExpr.CreateIdentString "dataNode" ]
|
[ SynExpr.CreateConst "data" ; SynExpr.createIdent "dataNode" ]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.tuple
|
||||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||||
|
|
||||||
let dataNode =
|
let dataNode =
|
||||||
SynExpr.CreateSequential (dataBindings @ [ assignToNode ])
|
SynExpr.sequential (dataBindings @ [ assignToNode ])
|
||||||
|> SynExpr.createLet [ dataNode ]
|
|> SynExpr.createLet [ dataNode ]
|
||||||
|
|
||||||
let action =
|
let action =
|
||||||
@@ -353,11 +316,11 @@ module internal JsonSerializeGenerator =
|
|||||||
if not dataBindings.IsEmpty then
|
if not dataBindings.IsEmpty then
|
||||||
yield dataNode
|
yield dataNode
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateSequential
|
|> SynExpr.sequential
|
||||||
|
|
||||||
SynMatchClause.Create (pattern, None, action)
|
SynMatchClause.create pattern action
|
||||||
)
|
)
|
||||||
|> fun clauses -> SynExpr.CreateMatch (SynExpr.CreateIdent inputArg, clauses)
|
|> SynExpr.createMatch (SynExpr.createIdent' inputArg)
|
||||||
|> scaffolding spec typeName inputArg
|
|> scaffolding spec typeName inputArg
|
||||||
|
|
||||||
let createModule
|
let createModule
|
||||||
@@ -374,12 +337,9 @@ module internal JsonSerializeGenerator =
|
|||||||
|
|
||||||
let attributes =
|
let attributes =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
[ SynAttribute.autoOpen ]
|
||||||
else
|
else
|
||||||
[
|
[ SynAttribute.requireQualifiedAccess ; SynAttribute.compilationRepresentation ]
|
||||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
|
||||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
|
||||||
]
|
|
||||||
|
|
||||||
let xmlDoc =
|
let xmlDoc =
|
||||||
let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "."
|
let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "."
|
||||||
@@ -391,7 +351,7 @@ module internal JsonSerializeGenerator =
|
|||||||
"methods"
|
"methods"
|
||||||
|
|
||||||
$"Module containing JSON serializing %s{description} for the %s{fullyQualified} type"
|
$"Module containing JSON serializing %s{description} for the %s{fullyQualified} type"
|
||||||
|> PreXmlDoc.Create
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let moduleName =
|
let moduleName =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
@@ -402,14 +362,16 @@ module internal JsonSerializeGenerator =
|
|||||||
List.last ident
|
List.last ident
|
||||||
|> fun i -> i.idText
|
|> fun i -> i.idText
|
||||||
|> fun s -> s + "JsonSerializeExtension"
|
|> fun s -> s + "JsonSerializeExtension"
|
||||||
|> Ident.Create
|
|> Ident.create
|
||||||
|
|
||||||
List.take (List.length ident - 1) ident @ [ expanded ]
|
List.take (List.length ident - 1) ident @ [ expanded ]
|
||||||
else
|
else
|
||||||
ident
|
ident
|
||||||
|
|
||||||
let info =
|
let info =
|
||||||
SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc)
|
SynComponentInfo.createLong moduleName
|
||||||
|
|> SynComponentInfo.addAttributes attributes
|
||||||
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
|
|
||||||
let decls =
|
let decls =
|
||||||
match synTypeDefnRepr with
|
match synTypeDefnRepr with
|
||||||
|
30
WoofWare.Myriad.Plugins/Primitives.fs
Normal file
30
WoofWare.Myriad.Plugins/Primitives.fs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal Primitives =
|
||||||
|
/// Given e.g. "byte", returns "System.Byte".
|
||||||
|
let qualifyType (typeName : string) : LongIdent option =
|
||||||
|
match typeName with
|
||||||
|
| "float32"
|
||||||
|
| "single" -> [ "System" ; "Single" ] |> Some
|
||||||
|
| "float"
|
||||||
|
| "double" -> [ "System" ; "Double" ] |> Some
|
||||||
|
| "byte"
|
||||||
|
| "uint8" -> [ "System" ; "Byte" ] |> Some
|
||||||
|
| "sbyte"
|
||||||
|
| "int8" -> [ "System" ; "SByte" ] |> Some
|
||||||
|
| "int16" -> [ "System" ; "Int16" ] |> Some
|
||||||
|
| "int"
|
||||||
|
| "int32" -> [ "System" ; "Int32" ] |> Some
|
||||||
|
| "int64" -> [ "System" ; "Int64" ] |> Some
|
||||||
|
| "uint16" -> [ "System" ; "UInt16" ] |> Some
|
||||||
|
| "uint"
|
||||||
|
| "uint32" -> [ "System" ; "UInt32" ] |> Some
|
||||||
|
| "uint64" -> [ "System" ; "UInt64" ] |> Some
|
||||||
|
| "char" -> [ "System" ; "Char" ] |> Some
|
||||||
|
| "decimal" -> [ "System" ; "Decimal" ] |> Some
|
||||||
|
| _ -> None
|
||||||
|
|> Option.map (List.map (fun i -> (Ident (i, range0))))
|
@@ -1,9 +1,7 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Fantomas.FCS.Xml
|
open Fantomas.FCS.Xml
|
||||||
open Myriad.Core
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal RemoveOptionsGenerator =
|
module internal RemoveOptionsGenerator =
|
||||||
@@ -47,7 +45,7 @@ module internal RemoveOptionsGenerator =
|
|||||||
(fields : SynField list)
|
(fields : SynField list)
|
||||||
=
|
=
|
||||||
let fields : SynField list = fields |> List.map removeOption
|
let fields : SynField list = fields |> List.map removeOption
|
||||||
let name = Ident.Create "Short"
|
let name = Ident.create "Short"
|
||||||
|
|
||||||
let record =
|
let record =
|
||||||
{
|
{
|
||||||
@@ -64,20 +62,10 @@ module internal RemoveOptionsGenerator =
|
|||||||
SynModuleDecl.Types ([ typeDecl ], range0)
|
SynModuleDecl.Types ([ typeDecl ], range0)
|
||||||
|
|
||||||
let createMaker (withOptionsType : LongIdent) (withoutOptionsType : LongIdent) (fields : SynFieldData<Ident> list) =
|
let createMaker (withOptionsType : LongIdent) (withoutOptionsType : LongIdent) (fields : SynFieldData<Ident> list) =
|
||||||
let xmlDoc = PreXmlDoc.Create " Remove the optional members of the input."
|
let xmlDoc = PreXmlDoc.create "Remove the optional members of the input."
|
||||||
|
|
||||||
let returnInfo =
|
let inputArg = Ident.create "input"
|
||||||
SynBindingReturnInfo.Create (SynType.LongIdent (SynLongIdent.CreateFromLongIdent withOptionsType))
|
let functionName = Ident.create "shorten"
|
||||||
|
|
||||||
let inputArg = Ident.Create "input"
|
|
||||||
let functionName = Ident.Create "shorten"
|
|
||||||
|
|
||||||
let inputVal =
|
|
||||||
SynValData.SynValData (
|
|
||||||
None,
|
|
||||||
SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty),
|
|
||||||
Some inputArg
|
|
||||||
)
|
|
||||||
|
|
||||||
let body =
|
let body =
|
||||||
fields
|
fields
|
||||||
@@ -93,63 +81,31 @@ module internal RemoveOptionsGenerator =
|
|||||||
let body =
|
let body =
|
||||||
match fieldData.Type with
|
match fieldData.Type with
|
||||||
| OptionType _ ->
|
| OptionType _ ->
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateAppInfix (
|
|
||||||
SynExpr.LongIdent (
|
|
||||||
false,
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_PipeRight" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "|>") ]
|
|
||||||
),
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
),
|
|
||||||
accessor
|
accessor
|
||||||
),
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "Option.defaultWith"),
|
(SynExpr.createLongIdent [ "Option" ; "defaultWith" ])
|
||||||
SynExpr.CreateLongIdent (
|
(SynExpr.createLongIdent' (
|
||||||
SynLongIdent.CreateFromLongIdent (
|
|
||||||
withoutOptionsType
|
withoutOptionsType
|
||||||
@ [ Ident.Create (sprintf "Default%s" fieldData.Ident.idText) ]
|
@ [ Ident.create (sprintf "Default%s" fieldData.Ident.idText) ]
|
||||||
)
|
))
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
| _ -> accessor
|
| _ -> accessor
|
||||||
|
|
||||||
(SynLongIdent.CreateFromLongIdent [ fieldData.Ident ], true), Some body
|
(SynLongIdent.createI fieldData.Ident, true), Some body
|
||||||
)
|
)
|
||||||
|> AstHelper.instantiateRecord
|
|> AstHelper.instantiateRecord
|
||||||
|
|
||||||
let pattern =
|
|
||||||
SynPat.LongIdent (
|
|
||||||
SynLongIdent.CreateFromLongIdent [ functionName ],
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
SynArgPats.Pats
|
|
||||||
[
|
|
||||||
SynPat.CreateTyped (
|
|
||||||
SynPat.CreateNamed inputArg,
|
|
||||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent withoutOptionsType)
|
|
||||||
)
|
|
||||||
|> SynPat.CreateParen
|
|
||||||
],
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
let binding =
|
let binding =
|
||||||
SynBinding.Let (
|
SynBinding.basic
|
||||||
isInline = false,
|
[ functionName ]
|
||||||
isMutable = false,
|
[
|
||||||
xmldoc = xmlDoc,
|
SynPat.named inputArg.idText
|
||||||
returnInfo = returnInfo,
|
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create withoutOptionsType))
|
||||||
expr = body,
|
]
|
||||||
valData = inputVal,
|
body
|
||||||
pattern = pattern
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
)
|
|> SynBinding.withReturnAnnotation (SynType.LongIdent (SynLongIdent.create withOptionsType))
|
||||||
|
|
||||||
SynModuleDecl.CreateLet [ binding ]
|
SynModuleDecl.CreateLet [ binding ]
|
||||||
|
|
||||||
@@ -167,13 +123,7 @@ module internal RemoveOptionsGenerator =
|
|||||||
let decls =
|
let decls =
|
||||||
[
|
[
|
||||||
createType (Some doc) accessibility typeParams fields
|
createType (Some doc) accessibility typeParams fields
|
||||||
createMaker [ Ident.Create "Short" ] recordId fieldData
|
createMaker [ Ident.create "Short" ] recordId fieldData
|
||||||
]
|
|
||||||
|
|
||||||
let attributes =
|
|
||||||
[
|
|
||||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
|
||||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
|
||||||
]
|
]
|
||||||
|
|
||||||
let xmlDoc =
|
let xmlDoc =
|
||||||
@@ -181,16 +131,21 @@ module internal RemoveOptionsGenerator =
|
|||||||
|> Seq.map (fun i -> i.idText)
|
|> Seq.map (fun i -> i.idText)
|
||||||
|> String.concat "."
|
|> String.concat "."
|
||||||
|> sprintf "Module containing an option-truncated version of the %s type"
|
|> sprintf "Module containing an option-truncated version of the %s type"
|
||||||
|> PreXmlDoc.Create
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let info =
|
let info =
|
||||||
SynComponentInfo.Create (recordId, attributes = attributes, xmldoc = xmlDoc)
|
SynComponentInfo.createLong recordId
|
||||||
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
|
|> SynComponentInfo.addAttributes [ SynAttribute.compilationRepresentation ]
|
||||||
|
|> SynComponentInfo.addAttributes [ SynAttribute.requireQualifiedAccess ]
|
||||||
|
|
||||||
let mdl = SynModuleDecl.CreateNestedModule (info, decls)
|
let mdl = SynModuleDecl.CreateNestedModule (info, decls)
|
||||||
|
|
||||||
SynModuleOrNamespace.CreateNamespace (namespaceId, decls = [ mdl ])
|
SynModuleOrNamespace.CreateNamespace (namespaceId, decls = [ mdl ])
|
||||||
| _ -> failwithf "Not a record type"
|
| _ -> failwithf "Not a record type"
|
||||||
|
|
||||||
|
open Myriad.Core
|
||||||
|
|
||||||
/// Myriad generator that stamps out a record with option types stripped
|
/// Myriad generator that stamps out a record with option types stripped
|
||||||
/// from the fields at the top level.
|
/// from the fields at the top level.
|
||||||
[<MyriadGenerator("remove-options")>]
|
[<MyriadGenerator("remove-options")>]
|
||||||
|
49
WoofWare.Myriad.Plugins/SynExpr/CompExpr.fs
Normal file
49
WoofWare.Myriad.Plugins/SynExpr/CompExpr.fs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
|
||||||
|
type internal CompExprBinding =
|
||||||
|
| LetBang of varName : string * rhs : SynExpr
|
||||||
|
| Let of varName : string * rhs : SynExpr
|
||||||
|
| Use of varName : string * rhs : SynExpr
|
||||||
|
| Do of body : SynExpr
|
||||||
|
|
||||||
|
(*
|
||||||
|
Potential API!
|
||||||
|
type internal CompExprBindings =
|
||||||
|
private
|
||||||
|
{
|
||||||
|
/// These are stored in reverse.
|
||||||
|
Bindings : CompExprBinding list
|
||||||
|
CompExprName : string
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal CompExprBindings =
|
||||||
|
let make (name : string) : CompExprBindings =
|
||||||
|
{
|
||||||
|
Bindings = []
|
||||||
|
CompExprName = name
|
||||||
|
}
|
||||||
|
|
||||||
|
let thenDo (body : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (Do body :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
let thenLet (varName : string) (value : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (Let (varName, value) :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
let thenLetBang (varName : string) (value : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (LetBang (varName, value) :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let thenUse (varName : string) (value : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (LetBang (varName, value) :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
*)
|
@@ -3,12 +3,14 @@ namespace WoofWare.Myriad.Plugins
|
|||||||
open System
|
open System
|
||||||
open System.Text
|
open System.Text
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Myriad.Core
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal Ident =
|
module internal Ident =
|
||||||
|
let inline create (s : string) = Ident (s, range0)
|
||||||
|
|
||||||
let lowerFirstLetter (x : Ident) : Ident =
|
let lowerFirstLetter (x : Ident) : Ident =
|
||||||
let result = StringBuilder x.idText.Length
|
let result = StringBuilder x.idText.Length
|
||||||
result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore
|
result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore
|
||||||
result.Append x.idText.[1..] |> ignore
|
result.Append x.idText.[1..] |> ignore
|
||||||
Ident.Create ((result : StringBuilder).ToString ())
|
create ((result : StringBuilder).ToString ())
|
9
WoofWare.Myriad.Plugins/SynExpr/PreXmlDoc.fs
Normal file
9
WoofWare.Myriad.Plugins/SynExpr/PreXmlDoc.fs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal PreXmlDoc =
|
||||||
|
let create (s : string) : PreXmlDoc =
|
||||||
|
PreXmlDoc.Create ([| " " + s |], range0)
|
@@ -1,7 +1,6 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.Text.Range
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal SynArgPats =
|
module internal SynArgPats =
|
||||||
@@ -11,8 +10,7 @@ module internal SynArgPats =
|
|||||||
else
|
else
|
||||||
|
|
||||||
caseNames
|
caseNames
|
||||||
|> List.map (fun ident -> SynPat.Named (SynIdent.SynIdent (ident, None), false, None, range0))
|
|> List.map (fun i -> SynPat.named i.idText)
|
||||||
|> fun ps -> SynPat.Tuple (false, ps, List.replicate (ps.Length - 1) range0, range0)
|
|> SynPat.tuple
|
||||||
|> fun p -> SynPat.Paren (p, range0)
|
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
|> SynArgPats.Pats
|
|> SynArgPats.Pats
|
||||||
|
@@ -2,20 +2,25 @@ namespace WoofWare.Myriad.Plugins
|
|||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
open Myriad.Core
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal SynAttribute =
|
module internal SynAttribute =
|
||||||
let internal compilationRepresentation : SynAttribute =
|
let internal compilationRepresentation : SynAttribute =
|
||||||
{
|
{
|
||||||
TypeName = SynLongIdent.CreateString "CompilationRepresentation"
|
TypeName = SynLongIdent.createS "CompilationRepresentation"
|
||||||
ArgExpr =
|
ArgExpr =
|
||||||
SynExpr.CreateLongIdent (
|
[ "CompilationRepresentationFlags" ; "ModuleSuffix" ]
|
||||||
false,
|
|> SynExpr.createLongIdent
|
||||||
SynLongIdent.Create [ "CompilationRepresentationFlags" ; "ModuleSuffix" ],
|
|> SynExpr.paren
|
||||||
None
|
Target = None
|
||||||
)
|
AppliesToGetterAndSetter = false
|
||||||
|> SynExpr.CreateParen
|
Range = range0
|
||||||
|
}
|
||||||
|
|
||||||
|
let internal requireQualifiedAccess : SynAttribute =
|
||||||
|
{
|
||||||
|
TypeName = SynLongIdent.createS "RequireQualifiedAccess"
|
||||||
|
ArgExpr = SynExpr.CreateConst ()
|
||||||
Target = None
|
Target = None
|
||||||
AppliesToGetterAndSetter = false
|
AppliesToGetterAndSetter = false
|
||||||
Range = range0
|
Range = range0
|
||||||
@@ -23,8 +28,8 @@ module internal SynAttribute =
|
|||||||
|
|
||||||
let internal autoOpen : SynAttribute =
|
let internal autoOpen : SynAttribute =
|
||||||
{
|
{
|
||||||
TypeName = SynLongIdent.CreateString "AutoOpen"
|
TypeName = SynLongIdent.createS "AutoOpen"
|
||||||
ArgExpr = SynExpr.CreateConst SynConst.Unit
|
ArgExpr = SynExpr.CreateConst ()
|
||||||
Target = None
|
Target = None
|
||||||
AppliesToGetterAndSetter = false
|
AppliesToGetterAndSetter = false
|
||||||
Range = range0
|
Range = range0
|
||||||
|
@@ -36,7 +36,7 @@ module internal SynBinding =
|
|||||||
SynLeadingKeyword.Let range0
|
SynLeadingKeyword.Let range0
|
||||||
}
|
}
|
||||||
|
|
||||||
let basic (name : SynLongIdent) (args : SynPat list) (body : SynExpr) : SynBinding =
|
let basic (name : LongIdent) (args : SynPat list) (body : SynExpr) : SynBinding =
|
||||||
let valInfo : SynValInfo =
|
let valInfo : SynValInfo =
|
||||||
args
|
args
|
||||||
|> List.map (fun pat -> [ SynArgInfo.SynArgInfo (SynAttributes.Empty, false, getName pat) ])
|
|> List.map (fun pat -> [ SynArgInfo.SynArgInfo (SynAttributes.Empty, false, getName pat) ])
|
||||||
@@ -50,7 +50,7 @@ module internal SynBinding =
|
|||||||
[],
|
[],
|
||||||
PreXmlDoc.Empty,
|
PreXmlDoc.Empty,
|
||||||
SynValData.SynValData (None, valInfo, None),
|
SynValData.SynValData (None, valInfo, None),
|
||||||
SynPat.LongIdent (name, None, None, SynArgPats.Pats args, None, range0),
|
SynPat.identWithArgs name (SynArgPats.Pats args),
|
||||||
None,
|
None,
|
||||||
body,
|
body,
|
||||||
range0,
|
range0,
|
||||||
|
50
WoofWare.Myriad.Plugins/SynExpr/SynComponentInfo.fs
Normal file
50
WoofWare.Myriad.Plugins/SynExpr/SynComponentInfo.fs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynComponentInfo =
|
||||||
|
let inline createLong (name : LongIdent) =
|
||||||
|
SynComponentInfo.SynComponentInfo ([], None, [], name, PreXmlDoc.Empty, false, None, range0)
|
||||||
|
|
||||||
|
let inline create (name : Ident) = createLong [ name ]
|
||||||
|
|
||||||
|
let inline withDocString (doc : PreXmlDoc) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, _, postfix, access, range) ->
|
||||||
|
SynComponentInfo (attrs, typars, constraints, name, doc, postfix, access, range)
|
||||||
|
|
||||||
|
let inline setGenerics (typars : SynTyparDecls option) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (attrs, _, constraints, name, doc, postfix, access, range) ->
|
||||||
|
SynComponentInfo (attrs, typars, constraints, name, doc, postfix, access, range)
|
||||||
|
|
||||||
|
let inline withGenerics (typars : SynTyparDecl list) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
let inner =
|
||||||
|
if typars.IsEmpty then
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some (SynTyparDecls.PostfixList (typars, [], range0))
|
||||||
|
|
||||||
|
setGenerics inner i
|
||||||
|
|
||||||
|
let inline setAccessibility (acc : SynAccess option) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, doc, postfix, _, range) ->
|
||||||
|
SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, doc, postfix, acc, range)
|
||||||
|
|
||||||
|
let inline withAccessibility (acc : SynAccess) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
setAccessibility (Some acc) i
|
||||||
|
|
||||||
|
let inline addAttributes (attrs : SynAttribute list) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (oldAttrs, typars, constraints, name, doc, postfix, acc, range) ->
|
||||||
|
let attrs =
|
||||||
|
{
|
||||||
|
SynAttributeList.Attributes = attrs
|
||||||
|
SynAttributeList.Range = range0
|
||||||
|
}
|
||||||
|
|
||||||
|
SynComponentInfo.SynComponentInfo ((attrs :: oldAttrs), typars, constraints, name, doc, postfix, acc, range)
|
@@ -3,14 +3,18 @@ namespace WoofWare.Myriad.Plugins
|
|||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
open Myriad.Core
|
open Myriad.Core
|
||||||
open Myriad.Core.Ast
|
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
type internal CompExprBinding =
|
[<AutoOpen>]
|
||||||
| LetBang of varName : string * rhs : SynExpr
|
module internal SynExprExtensions =
|
||||||
| Let of varName : string * rhs : SynExpr
|
type SynExpr with
|
||||||
| Use of varName : string * rhs : SynExpr
|
static member CreateConst (s : string) : SynExpr =
|
||||||
| Do of body : SynExpr
|
SynExpr.Const (SynConst.String (s, SynStringKind.Regular, range0), range0)
|
||||||
|
|
||||||
|
static member CreateConst () : SynExpr = SynExpr.Const (SynConst.Unit, range0)
|
||||||
|
|
||||||
|
static member CreateConst (i : int32) : SynExpr =
|
||||||
|
SynExpr.Const (SynConst.Int32 i, range0)
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal SynExpr =
|
module internal SynExpr =
|
||||||
@@ -19,20 +23,11 @@ module internal SynExpr =
|
|||||||
let applyFunction (f : SynExpr) (x : SynExpr) : SynExpr = SynExpr.CreateApp (f, x)
|
let applyFunction (f : SynExpr) (x : SynExpr) : SynExpr = SynExpr.CreateApp (f, x)
|
||||||
|
|
||||||
/// {f} {x}
|
/// {f} {x}
|
||||||
let applyTo (x : SynExpr) (f : SynExpr) : SynExpr = SynExpr.CreateApp (f, x)
|
let inline applyTo (x : SynExpr) (f : SynExpr) : SynExpr = applyFunction f x
|
||||||
|
|
||||||
/// {expr} |> {func}
|
/// {expr} |> {func}
|
||||||
let pipeThroughFunction (func : SynExpr) (expr : SynExpr) : SynExpr =
|
let pipeThroughFunction (func : SynExpr) (expr : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateAppInfix (
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.pipe, expr)
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_PipeRight" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "|>") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
expr
|
|
||||||
)
|
|
||||||
|> applyTo func
|
|> applyTo func
|
||||||
|
|
||||||
/// if {cond} then {trueBranch} else {falseBranch}
|
/// if {cond} then {trueBranch} else {falseBranch}
|
||||||
@@ -58,7 +53,7 @@ module internal SynExpr =
|
|||||||
/// try {body} with | {exc} as exc -> {handler}
|
/// try {body} with | {exc} as exc -> {handler}
|
||||||
let pipeThroughTryWith (exc : SynPat) (handler : SynExpr) (body : SynExpr) : SynExpr =
|
let pipeThroughTryWith (exc : SynPat) (handler : SynExpr) (body : SynExpr) : SynExpr =
|
||||||
let clause =
|
let clause =
|
||||||
SynMatchClause.Create (SynPat.As (exc, SynPat.CreateNamed (Ident.Create "exc"), range0), None, handler)
|
SynMatchClause.create (SynPat.As (exc, SynPat.named "exc", range0)) handler
|
||||||
|
|
||||||
SynExpr.TryWith (
|
SynExpr.TryWith (
|
||||||
body,
|
body,
|
||||||
@@ -76,17 +71,7 @@ module internal SynExpr =
|
|||||||
|
|
||||||
/// {a} = {b}
|
/// {a} = {b}
|
||||||
let equals (a : SynExpr) (b : SynExpr) =
|
let equals (a : SynExpr) (b : SynExpr) =
|
||||||
SynExpr.CreateAppInfix (
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.eq, a) |> applyTo b
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
Ident.CreateLong "op_Equality",
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "=") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
a
|
|
||||||
)
|
|
||||||
|> applyTo b
|
|
||||||
|
|
||||||
/// {a} + {b}
|
/// {a} + {b}
|
||||||
let plus (a : SynExpr) (b : SynExpr) =
|
let plus (a : SynExpr) (b : SynExpr) =
|
||||||
@@ -112,46 +97,49 @@ module internal SynExpr =
|
|||||||
SynExpr.DotGet (
|
SynExpr.DotGet (
|
||||||
obj,
|
obj,
|
||||||
range0,
|
range0,
|
||||||
SynLongIdent.SynLongIdent (id = [ Ident.Create meth ], dotRanges = [], trivia = [ None ]),
|
SynLongIdent.SynLongIdent (id = [ Ident.create meth ], dotRanges = [], trivia = [ None ]),
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
|> applyTo arg
|
|> applyTo arg
|
||||||
|
|
||||||
/// {obj}.{meth}()
|
/// {obj}.{meth}()
|
||||||
let callMethod (meth : string) (obj : SynExpr) : SynExpr =
|
let callMethod (meth : string) (obj : SynExpr) : SynExpr =
|
||||||
callMethodArg meth (SynExpr.CreateConst SynConst.Unit) obj
|
callMethodArg meth (SynExpr.CreateConst ()) obj
|
||||||
|
|
||||||
let callGenericMethod (meth : string) (ty : LongIdent) (obj : SynExpr) : SynExpr =
|
let callGenericMethod (meth : string) (ty : LongIdent) (obj : SynExpr) : SynExpr =
|
||||||
SynExpr.TypeApp (
|
SynExpr.TypeApp (
|
||||||
SynExpr.DotGet (obj, range0, SynLongIdent.Create [ meth ], range0),
|
SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0),
|
||||||
range0,
|
range0,
|
||||||
[ SynType.LongIdent (SynLongIdent.CreateFromLongIdent ty) ],
|
[ SynType.LongIdent (SynLongIdent.create ty) ],
|
||||||
[],
|
[],
|
||||||
Some range0,
|
Some range0,
|
||||||
range0,
|
range0,
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
|> applyTo (SynExpr.CreateConst SynConst.Unit)
|
|> applyTo (SynExpr.CreateConst ())
|
||||||
|
|
||||||
/// {obj}.{meth}<ty>()
|
/// {obj}.{meth}<ty>()
|
||||||
let callGenericMethod' (meth : string) (ty : string) (obj : SynExpr) : SynExpr =
|
let callGenericMethod' (meth : string) (ty : string) (obj : SynExpr) : SynExpr =
|
||||||
SynExpr.TypeApp (
|
SynExpr.TypeApp (
|
||||||
SynExpr.DotGet (obj, range0, SynLongIdent.Create [ meth ], range0),
|
SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0),
|
||||||
range0,
|
range0,
|
||||||
[ SynType.CreateLongIdent ty ],
|
[ SynType.createLongIdent' [ ty ] ],
|
||||||
[],
|
[],
|
||||||
Some range0,
|
Some range0,
|
||||||
range0,
|
range0,
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
|> applyTo (SynExpr.CreateConst SynConst.Unit)
|
|> applyTo (SynExpr.CreateConst ())
|
||||||
|
|
||||||
let index (property : SynExpr) (obj : SynExpr) : SynExpr =
|
let inline index (property : SynExpr) (obj : SynExpr) : SynExpr =
|
||||||
SynExpr.DotIndexedGet (obj, property, range0, range0)
|
SynExpr.DotIndexedGet (obj, property, range0, range0)
|
||||||
|
|
||||||
|
let inline paren (e : SynExpr) : SynExpr =
|
||||||
|
SynExpr.Paren (e, range0, Some range0, range0)
|
||||||
|
|
||||||
/// (fun {varName} -> {body})
|
/// (fun {varName} -> {body})
|
||||||
let createLambda (varName : string) (body : SynExpr) : SynExpr =
|
let createLambda (varName : string) (body : SynExpr) : SynExpr =
|
||||||
let parsedDataPat = [ SynPat.CreateNamed (Ident.Create varName) ]
|
let parsedDataPat = [ SynPat.named varName ]
|
||||||
|
|
||||||
SynExpr.Lambda (
|
SynExpr.Lambda (
|
||||||
false,
|
false,
|
||||||
@@ -164,39 +152,82 @@ module internal SynExpr =
|
|||||||
ArrowRange = Some range0
|
ArrowRange = Some range0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|> SynExpr.CreateParen
|
|> paren
|
||||||
|
|
||||||
let reraise : SynExpr =
|
let createThunk (body : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateIdent (Ident.Create "reraise")
|
SynExpr.Lambda (
|
||||||
|> applyTo (SynExpr.CreateConst SynConst.Unit)
|
false,
|
||||||
|
false,
|
||||||
|
SynSimplePats.Create [],
|
||||||
|
body,
|
||||||
|
Some ([ SynPat.unit ], body),
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
ArrowRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> paren
|
||||||
|
|
||||||
|
let inline createIdent (s : string) : SynExpr = SynExpr.Ident (Ident (s, range0))
|
||||||
|
|
||||||
|
let inline createIdent' (i : Ident) : SynExpr = SynExpr.Ident i
|
||||||
|
|
||||||
|
let inline createLongIdent' (ident : Ident list) : SynExpr =
|
||||||
|
SynExpr.LongIdent (false, SynLongIdent.create ident, None, range0)
|
||||||
|
|
||||||
|
let inline createLongIdent (ident : string list) : SynExpr =
|
||||||
|
createLongIdent' (ident |> List.map Ident.create)
|
||||||
|
|
||||||
|
let tupleNoParen (args : SynExpr list) : SynExpr =
|
||||||
|
SynExpr.Tuple (false, args, List.replicate (args.Length - 1) range0, range0)
|
||||||
|
|
||||||
|
let inline tuple (args : SynExpr list) = args |> tupleNoParen |> paren
|
||||||
|
|
||||||
/// {body} |> fun a -> Async.StartAsTask (a, ?cancellationToken=ct)
|
/// {body} |> fun a -> Async.StartAsTask (a, ?cancellationToken=ct)
|
||||||
let startAsTask (ct : SynLongIdent) (body : SynExpr) =
|
let startAsTask (ct : Ident) (body : SynExpr) =
|
||||||
let lambda =
|
let lambda =
|
||||||
[
|
[
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "a")
|
createIdent "a"
|
||||||
equals
|
equals
|
||||||
(SynExpr.LongIdent (true, SynLongIdent.CreateString "cancellationToken", None, range0))
|
(SynExpr.LongIdent (true, SynLongIdent.createS "cancellationToken", None, range0))
|
||||||
(SynExpr.CreateLongIdent ct)
|
(createIdent' ct)
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> tuple
|
||||||
|> applyFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "StartAsTask" ]))
|
|> applyFunction (createLongIdent [ "Async" ; "StartAsTask" ])
|
||||||
|> createLambda "a"
|
|> createLambda "a"
|
||||||
|
|
||||||
pipeThroughFunction lambda body
|
pipeThroughFunction lambda body
|
||||||
|
|
||||||
let createLongIdent (ident : string list) : SynExpr =
|
let inline createLet (bindings : SynBinding list) (body : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create ident)
|
|
||||||
|
|
||||||
let createLongIdent' (ident : Ident list) : SynExpr =
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent ident)
|
|
||||||
|
|
||||||
let createLet (bindings : SynBinding list) (body : SynExpr) : SynExpr =
|
|
||||||
SynExpr.LetOrUse (false, false, bindings, body, range0, SynExprLetOrUseTrivia.empty)
|
SynExpr.LetOrUse (false, false, bindings, body, range0, SynExprLetOrUseTrivia.empty)
|
||||||
|
|
||||||
let createMatch (matchOn : SynExpr) (cases : SynMatchClause list) : SynExpr = SynExpr.CreateMatch (matchOn, cases)
|
let inline createMatch (matchOn : SynExpr) (cases : SynMatchClause list) : SynExpr =
|
||||||
|
SynExpr.Match (
|
||||||
|
DebugPointAtBinding.Yes range0,
|
||||||
|
matchOn,
|
||||||
|
cases,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
MatchKeyword = range0
|
||||||
|
WithKeyword = range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
let typeAnnotate (ty : SynType) (expr : SynExpr) : SynExpr = SynExpr.CreateTyped (expr, ty)
|
let typeAnnotate (ty : SynType) (expr : SynExpr) : SynExpr = SynExpr.Typed (expr, ty, range0)
|
||||||
|
|
||||||
|
let inline createNew (ty : SynType) (args : SynExpr) : SynExpr =
|
||||||
|
SynExpr.New (false, ty, paren args, range0)
|
||||||
|
|
||||||
|
let inline createWhile (cond : SynExpr) (body : SynExpr) : SynExpr =
|
||||||
|
SynExpr.While (DebugPointAtWhile.Yes range0, cond, body, range0)
|
||||||
|
|
||||||
|
let inline createNull () : SynExpr = SynExpr.Null range0
|
||||||
|
|
||||||
|
let reraise : SynExpr = createIdent "reraise" |> applyTo (SynExpr.CreateConst ())
|
||||||
|
|
||||||
|
let sequential (exprs : SynExpr list) : SynExpr =
|
||||||
|
exprs
|
||||||
|
|> List.reduce (fun a b -> SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, false, a, b, range0))
|
||||||
|
|
||||||
/// {compExpr} { {lets} ; return {ret} }
|
/// {compExpr} { {lets} ; return {ret} }
|
||||||
let createCompExpr (compExpr : string) (retBody : SynExpr) (lets : CompExprBinding list) : SynExpr =
|
let createCompExpr (compExpr : string) (retBody : SynExpr) (lets : CompExprBinding list) : SynExpr =
|
||||||
@@ -211,7 +242,7 @@ module internal SynExpr =
|
|||||||
DebugPointAtBinding.Yes range0,
|
DebugPointAtBinding.Yes range0,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
SynPat.CreateNamed (Ident.Create lhs),
|
SynPat.named lhs,
|
||||||
rhs,
|
rhs,
|
||||||
[],
|
[],
|
||||||
state,
|
state,
|
||||||
@@ -220,90 +251,50 @@ module internal SynExpr =
|
|||||||
EqualsRange = Some range0
|
EqualsRange = Some range0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
| Let (lhs, rhs) ->
|
| Let (lhs, rhs) -> createLet [ SynBinding.basic [ Ident.create lhs ] [] rhs ] state
|
||||||
createLet [ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ] state
|
|
||||||
| Use (lhs, rhs) ->
|
| Use (lhs, rhs) ->
|
||||||
SynExpr.LetOrUse (
|
SynExpr.LetOrUse (
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
[ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ],
|
[ SynBinding.basic [ Ident.create lhs ] [] rhs ],
|
||||||
state,
|
state,
|
||||||
range0,
|
range0,
|
||||||
{
|
{
|
||||||
SynExprLetOrUseTrivia.InKeyword = None
|
SynExprLetOrUseTrivia.InKeyword = None
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
| Do body -> SynExpr.CreateSequential [ SynExpr.Do (body, range0) ; state ]
|
| Do body -> sequential [ SynExpr.Do (body, range0) ; state ]
|
||||||
)
|
)
|
||||||
|
|
||||||
SynExpr.CreateApp (
|
applyFunction (createIdent compExpr) (SynExpr.ComputationExpr (false, contents, range0))
|
||||||
SynExpr.CreateIdent (Ident.Create compExpr),
|
|
||||||
SynExpr.ComputationExpr (false, contents, range0)
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {expr} |> Async.AwaitTask
|
/// {expr} |> Async.AwaitTask
|
||||||
let awaitTask (expr : SynExpr) : SynExpr =
|
let awaitTask (expr : SynExpr) : SynExpr =
|
||||||
expr
|
expr |> pipeThroughFunction (createLongIdent [ "Async" ; "AwaitTask" ])
|
||||||
|> pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "AwaitTask" ]))
|
|
||||||
|
|
||||||
/// {ident}.ToString ()
|
/// {ident}.ToString ()
|
||||||
/// with special casing for some types like DateTime
|
/// with special casing for some types like DateTime
|
||||||
let toString (ty : SynType) (ident : SynExpr) =
|
let toString (ty : SynType) (ident : SynExpr) =
|
||||||
match ty with
|
match ty with
|
||||||
| DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-dd")
|
| DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-dd")
|
||||||
| DateTime ->
|
| DateTime -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-ddTHH:mm:ss")
|
||||||
ident
|
|
||||||
|> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-ddTHH:mm:ss")
|
|
||||||
| _ -> callMethod "ToString" ident
|
| _ -> callMethod "ToString" ident
|
||||||
|
|
||||||
let upcast' (ty : SynType) (e : SynExpr) = SynExpr.Upcast (e, ty, range0)
|
let upcast' (ty : SynType) (e : SynExpr) = SynExpr.Upcast (e, ty, range0)
|
||||||
|
|
||||||
/// {ident} - {rhs}
|
/// {ident} - {rhs}
|
||||||
let minus (ident : SynLongIdent) (rhs : SynExpr) : SynExpr =
|
let minus (ident : SynLongIdent) (rhs : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateApp (
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.sub, SynExpr.CreateLongIdent ident)
|
||||||
SynExpr.CreateAppInfix (
|
|> applyTo rhs
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_Subtraction" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "-") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
SynExpr.CreateLongIdent ident
|
|
||||||
),
|
|
||||||
rhs
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {ident} - {n}
|
/// {ident} - {n}
|
||||||
let minusN (ident : SynLongIdent) (n : int) : SynExpr =
|
let minusN (ident : SynLongIdent) (n : int) : SynExpr = minus ident (SynExpr.CreateConst n)
|
||||||
minus ident (SynExpr.CreateConst (SynConst.Int32 n))
|
|
||||||
|
|
||||||
/// {y} > {x}
|
/// {y} > {x}
|
||||||
let greaterThan (x : SynExpr) (y : SynExpr) : SynExpr =
|
let greaterThan (x : SynExpr) (y : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateApp (
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.ge, y) |> applyTo x
|
||||||
SynExpr.CreateAppInfix (
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_GreaterThan" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation ">") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
y
|
|
||||||
),
|
|
||||||
x
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {y} >= {x}
|
/// {y} >= {x}
|
||||||
let greaterThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr =
|
let greaterThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateAppInfix (
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.geq, y)
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_GreaterThanOrEqual" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation ">=") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
y
|
|
||||||
)
|
|
||||||
|> applyTo x
|
|> applyTo x
|
||||||
|
106
WoofWare.Myriad.Plugins/SynExpr/SynLongIdent.fs
Normal file
106
WoofWare.Myriad.Plugins/SynExpr/SynLongIdent.fs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynLongIdent =
|
||||||
|
|
||||||
|
let geq =
|
||||||
|
SynLongIdent.SynLongIdent (
|
||||||
|
[ Ident.create "op_GreaterThanOrEqual" ],
|
||||||
|
[],
|
||||||
|
[ Some (IdentTrivia.OriginalNotation ">=") ]
|
||||||
|
)
|
||||||
|
|
||||||
|
let ge =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_GreaterThan" ], [], [ Some (IdentTrivia.OriginalNotation ">") ])
|
||||||
|
|
||||||
|
let sub =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_Subtraction" ], [], [ Some (IdentTrivia.OriginalNotation "-") ])
|
||||||
|
|
||||||
|
let eq =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_Equality" ], [], [ Some (IdentTrivia.OriginalNotation "=") ])
|
||||||
|
|
||||||
|
let pipe =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_PipeRight" ], [], [ Some (IdentTrivia.OriginalNotation "|>") ])
|
||||||
|
|
||||||
|
let toString (sli : SynLongIdent) : string =
|
||||||
|
sli.LongIdent |> List.map _.idText |> String.concat "."
|
||||||
|
|
||||||
|
let create (ident : LongIdent) : SynLongIdent =
|
||||||
|
let commas =
|
||||||
|
match ident with
|
||||||
|
| [] -> []
|
||||||
|
| _ :: commas -> commas |> List.map (fun _ -> range0)
|
||||||
|
|
||||||
|
SynLongIdent.SynLongIdent (ident, commas, List.replicate ident.Length None)
|
||||||
|
|
||||||
|
let inline createI (i : Ident) : SynLongIdent = create [ i ]
|
||||||
|
|
||||||
|
let inline createS (s : string) : SynLongIdent = createI (Ident (s, range0))
|
||||||
|
|
||||||
|
let inline createS' (s : string list) : SynLongIdent =
|
||||||
|
create (s |> List.map (fun i -> Ident (i, range0)))
|
||||||
|
|
||||||
|
let isUnit (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when System.String.Equals (i.idText, "unit", System.StringComparison.OrdinalIgnoreCase) -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isList (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true
|
||||||
|
// TODO: consider FSharpList or whatever it is
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isArray (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when
|
||||||
|
System.String.Equals (i.idText, "array", System.StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| System.String.Equals (i.idText, "[]", System.StringComparison.Ordinal)
|
||||||
|
->
|
||||||
|
true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isOption (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when System.String.Equals (i.idText, "option", System.StringComparison.OrdinalIgnoreCase) -> true
|
||||||
|
// TODO: consider Microsoft.FSharp.Option or whatever it is
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isResponse (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "Response" ]
|
||||||
|
| [ "RestEase" ; "Response" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isMap (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "Map" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isReadOnlyDictionary (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "IReadOnlyDictionary" ]
|
||||||
|
| [ "Generic" ; "IReadOnlyDictionary" ]
|
||||||
|
| [ "Collections" ; "Generic" ; "IReadOnlyDictionary" ]
|
||||||
|
| [ "System" ; "Collections" ; "Generic" ; "IReadOnlyDictionary" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isDictionary (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "Dictionary" ]
|
||||||
|
| [ "Generic" ; "Dictionary" ]
|
||||||
|
| [ "Collections" ; "Generic" ; "Dictionary" ]
|
||||||
|
| [ "System" ; "Collections" ; "Generic" ; "Dictionary" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isIDictionary (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "IDictionary" ]
|
||||||
|
| [ "Generic" ; "IDictionary" ]
|
||||||
|
| [ "Collections" ; "Generic" ; "IDictionary" ]
|
||||||
|
| [ "System" ; "Collections" ; "Generic" ; "IDictionary" ] -> true
|
||||||
|
| _ -> false
|
24
WoofWare.Myriad.Plugins/SynExpr/SynMatchClause.fs
Normal file
24
WoofWare.Myriad.Plugins/SynExpr/SynMatchClause.fs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynMatchClause =
|
||||||
|
let create (lhs : SynPat) (rhs : SynExpr) : SynMatchClause =
|
||||||
|
SynMatchClause.SynMatchClause (
|
||||||
|
lhs,
|
||||||
|
None,
|
||||||
|
rhs,
|
||||||
|
range0,
|
||||||
|
DebugPointAtTarget.Yes,
|
||||||
|
{
|
||||||
|
ArrowRange = Some range0
|
||||||
|
BarRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let withWhere (where : SynExpr) (m : SynMatchClause) : SynMatchClause =
|
||||||
|
match m with
|
||||||
|
| SynMatchClause (synPat, _, resultExpr, range, debugPointAtTarget, synMatchClauseTrivia) ->
|
||||||
|
SynMatchClause (synPat, Some where, resultExpr, range, debugPointAtTarget, synMatchClauseTrivia)
|
61
WoofWare.Myriad.Plugins/SynExpr/SynMemberDefn.fs
Normal file
61
WoofWare.Myriad.Plugins/SynExpr/SynMemberDefn.fs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynMemberDefn =
|
||||||
|
let private interfaceMemberSlotFlags =
|
||||||
|
{
|
||||||
|
SynMemberFlags.IsInstance = true
|
||||||
|
SynMemberFlags.IsDispatchSlot = true
|
||||||
|
SynMemberFlags.IsOverrideOrExplicitImpl = false
|
||||||
|
SynMemberFlags.IsFinal = false
|
||||||
|
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
||||||
|
SynMemberFlags.MemberKind = SynMemberKind.Member
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let abstractMember
|
||||||
|
(ident : SynIdent)
|
||||||
|
(typars : SynTyparDecls option)
|
||||||
|
(arity : SynValInfo)
|
||||||
|
(xmlDoc : PreXmlDoc)
|
||||||
|
(returnType : SynType)
|
||||||
|
: SynMemberDefn
|
||||||
|
=
|
||||||
|
let slot =
|
||||||
|
SynValSig.SynValSig (
|
||||||
|
[],
|
||||||
|
ident,
|
||||||
|
SynValTyparDecls.SynValTyparDecls (typars, true),
|
||||||
|
returnType,
|
||||||
|
arity,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
xmlDoc,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
EqualsRange = None
|
||||||
|
WithKeyword = None
|
||||||
|
InlineKeyword = None
|
||||||
|
LeadingKeyword = SynLeadingKeyword.Abstract range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
SynMemberDefn.AbstractSlot (
|
||||||
|
slot,
|
||||||
|
interfaceMemberSlotFlags,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
GetSetKeywords = None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let staticMember (binding : SynBinding) : SynMemberDefn =
|
||||||
|
let binding = SynBinding.makeStaticMember binding
|
||||||
|
SynMemberDefn.Member (binding, range0)
|
@@ -6,5 +6,28 @@ open Fantomas.FCS.Text.Range
|
|||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal SynPat =
|
module internal SynPat =
|
||||||
|
|
||||||
let annotateType (ty : SynType) (pat : SynPat) =
|
let inline annotateType (ty : SynType) (pat : SynPat) =
|
||||||
SynPat.Paren (SynPat.Typed (pat, ty, range0), range0)
|
SynPat.Paren (SynPat.Typed (pat, ty, range0), range0)
|
||||||
|
|
||||||
|
let inline named (s : string) : SynPat =
|
||||||
|
SynPat.Named (SynIdent.SynIdent (Ident (s, range0), None), false, None, range0)
|
||||||
|
|
||||||
|
let inline namedI (i : Ident) : SynPat =
|
||||||
|
SynPat.Named (SynIdent.SynIdent (i, None), false, None, range0)
|
||||||
|
|
||||||
|
let inline identWithArgs (i : LongIdent) (args : SynArgPats) : SynPat =
|
||||||
|
SynPat.LongIdent (SynLongIdent.create i, None, None, args, None, range0)
|
||||||
|
|
||||||
|
let inline tupleNoParen (elements : SynPat list) : SynPat =
|
||||||
|
match elements with
|
||||||
|
| [] -> failwith "Can't tuple no elements in a pattern"
|
||||||
|
| [ p ] -> p
|
||||||
|
| elements -> SynPat.Tuple (false, elements, List.replicate (elements.Length - 1) range0, range0)
|
||||||
|
|
||||||
|
let inline paren (pat : SynPat) : SynPat = SynPat.Paren (pat, range0)
|
||||||
|
|
||||||
|
let inline tuple (elements : SynPat list) : SynPat = tupleNoParen elements |> paren
|
||||||
|
|
||||||
|
let unit = SynPat.Const (SynConst.Unit, range0)
|
||||||
|
|
||||||
|
let createNull = SynPat.Null range0
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal SynType =
|
module internal SynType =
|
||||||
@@ -8,3 +9,227 @@ module internal SynType =
|
|||||||
match ty with
|
match ty with
|
||||||
| SynType.Paren (ty, _) -> stripOptionalParen ty
|
| SynType.Paren (ty, _) -> stripOptionalParen ty
|
||||||
| ty -> ty
|
| ty -> ty
|
||||||
|
|
||||||
|
let inline createLongIdent (ident : LongIdent) : SynType =
|
||||||
|
SynType.LongIdent (SynLongIdent.create ident)
|
||||||
|
|
||||||
|
let inline createLongIdent' (ident : string list) : SynType =
|
||||||
|
SynType.LongIdent (SynLongIdent.createS' ident)
|
||||||
|
|
||||||
|
let inline named (name : string) = createLongIdent' [ name ]
|
||||||
|
|
||||||
|
let inline app' (name : SynType) (args : SynType list) : SynType =
|
||||||
|
if args.IsEmpty then
|
||||||
|
failwith "Type cannot be applied to no arguments"
|
||||||
|
|
||||||
|
SynType.App (name, Some range0, args, List.replicate (args.Length - 1) range0, Some range0, false, range0)
|
||||||
|
|
||||||
|
let inline app (name : string) (args : SynType list) : SynType = app' (named name) args
|
||||||
|
|
||||||
|
let inline appPostfix (name : string) (arg : SynType) : SynType =
|
||||||
|
SynType.App (named name, None, [ arg ], [], None, true, range0)
|
||||||
|
|
||||||
|
let inline funFromDomain (domain : SynType) (range : SynType) : SynType =
|
||||||
|
SynType.Fun (
|
||||||
|
domain,
|
||||||
|
range,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
ArrowRange = range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let inline signatureParamOfType (ty : SynType) (name : Ident option) : SynType =
|
||||||
|
SynType.SignatureParameter ([], false, name, ty, range0)
|
||||||
|
|
||||||
|
let inline var (ty : SynTypar) : SynType = SynType.Var (ty, range0)
|
||||||
|
|
||||||
|
let unit : SynType = named "unit"
|
||||||
|
let int : SynType = named "int"
|
||||||
|
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal SynTypePatterns =
|
||||||
|
let (|OptionType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isOption ident ->
|
||||||
|
Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|UnitType|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident when SynLongIdent.isUnit ident -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|ListType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isList ident ->
|
||||||
|
Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|ArrayType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isArray ident ->
|
||||||
|
Some innerType
|
||||||
|
| SynType.Array (1, innerType, _) -> Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|RestEaseResponseType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isResponse ident ->
|
||||||
|
Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|DictionaryType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isDictionary ident ->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|IDictionaryType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isIDictionary ident ->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|IReadOnlyDictionaryType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when
|
||||||
|
SynLongIdent.isReadOnlyDictionary ident
|
||||||
|
->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|MapType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isMap ident ->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|BigInt|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "bigint" ]
|
||||||
|
| [ "BigInteger" ]
|
||||||
|
| [ "Numerics" ; "BigInteger" ]
|
||||||
|
| [ "System" ; "Numerics" ; "BigInteger" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
/// Returns the type, qualified as in e.g. `System.Boolean`.
|
||||||
|
let (|PrimitiveType|_|) (fieldType : SynType) : LongIdent option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] -> Primitives.qualifyType i.idText
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|String|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] ->
|
||||||
|
[ "string" ]
|
||||||
|
|> List.tryFind (fun s -> s = i.idText)
|
||||||
|
|> Option.map ignore<string>
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Byte|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] -> [ "byte" ] |> List.tryFind (fun s -> s = i.idText) |> Option.map ignore<string>
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Guid|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Guid" ]
|
||||||
|
| [ "Guid" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|HttpResponseMessage|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Net" ; "Http" ; "HttpResponseMessage" ]
|
||||||
|
| [ "Net" ; "Http" ; "HttpResponseMessage" ]
|
||||||
|
| [ "Http" ; "HttpResponseMessage" ]
|
||||||
|
| [ "HttpResponseMessage" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|HttpContent|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Net" ; "Http" ; "HttpContent" ]
|
||||||
|
| [ "Net" ; "Http" ; "HttpContent" ]
|
||||||
|
| [ "Http" ; "HttpContent" ]
|
||||||
|
| [ "HttpContent" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Stream|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "IO" ; "Stream" ]
|
||||||
|
| [ "IO" ; "Stream" ]
|
||||||
|
| [ "Stream" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|NumberType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] -> [ "string" ; "float" ; "int" ; "bool" ] |> List.tryFind (fun s -> s = i.idText)
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|DateOnly|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "DateOnly" ]
|
||||||
|
| [ "DateOnly" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|DateTime|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "DateTime" ]
|
||||||
|
| [ "DateTime" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Uri|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Uri" ]
|
||||||
|
| [ "Uri" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Task|_|) (fieldType : SynType) : SynType option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)), _, args, _, _, _, _) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "Task" ]
|
||||||
|
| [ "Tasks" ; "Task" ]
|
||||||
|
| [ "Threading" ; "Tasks" ; "Task" ]
|
||||||
|
| [ "System" ; "Threading" ; "Tasks" ; "Task" ] ->
|
||||||
|
match args with
|
||||||
|
| [ arg ] -> Some arg
|
||||||
|
| _ -> failwithf "Expected Task to be applied to exactly one arg, but got: %+A" args
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
27
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefn.fs
Normal file
27
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefn.fs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynTypeDefn =
|
||||||
|
|
||||||
|
let inline create (componentInfo : SynComponentInfo) (repr : SynTypeDefnRepr) : SynTypeDefn =
|
||||||
|
SynTypeDefn.SynTypeDefn (
|
||||||
|
componentInfo,
|
||||||
|
repr,
|
||||||
|
[],
|
||||||
|
None,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||||
|
EqualsRange = Some range0
|
||||||
|
WithKeyword = None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let inline withMemberDefns (members : SynMemberDefn list) (r : SynTypeDefn) : SynTypeDefn =
|
||||||
|
match r with
|
||||||
|
| SynTypeDefn (typeInfo, typeRepr, _, ctor, range, trivia) ->
|
||||||
|
SynTypeDefn.SynTypeDefn (typeInfo, typeRepr, members, ctor, range, trivia)
|
20
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefnRepr.fs
Normal file
20
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefnRepr.fs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynTypeDefnRepr =
|
||||||
|
|
||||||
|
let inline interfaceType (mems : SynMemberDefns) : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Unspecified, mems, range0)
|
||||||
|
|
||||||
|
/// Indicates the body of a `type Foo with {body}` extension type declaration.
|
||||||
|
let inline augmentation () : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0)
|
||||||
|
|
||||||
|
let inline union (cases : SynUnionCase list) : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (None, cases, range0), range0)
|
||||||
|
|
||||||
|
let inline record (fields : SynField list) : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, fields, range0), range0)
|
@@ -25,17 +25,26 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="List.fs"/>
|
<Compile Include="List.fs"/>
|
||||||
<Compile Include="Ident.fs" />
|
<Compile Include="Primitives.fs" />
|
||||||
<Compile Include="AstHelper.fs"/>
|
<Compile Include="SynExpr\PreXmlDoc.fs" />
|
||||||
|
<Compile Include="SynExpr\Ident.fs" />
|
||||||
|
<Compile Include="SynExpr\SynLongIdent.fs" />
|
||||||
<Compile Include="SynExpr\SynExprLetOrUseTrivia.fs" />
|
<Compile Include="SynExpr\SynExprLetOrUseTrivia.fs" />
|
||||||
|
<Compile Include="SynExpr\SynPat.fs" />
|
||||||
<Compile Include="SynExpr\SynBinding.fs" />
|
<Compile Include="SynExpr\SynBinding.fs" />
|
||||||
<Compile Include="SynExpr\SynExpr.fs" />
|
|
||||||
<Compile Include="SynExpr\SynType.fs" />
|
<Compile Include="SynExpr\SynType.fs" />
|
||||||
<Compile Include="SynExpr\SynAttribute.fs" />
|
<Compile Include="SynExpr\SynMatchClause.fs" />
|
||||||
|
<Compile Include="SynExpr\CompExpr.fs" />
|
||||||
|
<Compile Include="SynExpr\SynExpr.fs" />
|
||||||
<Compile Include="SynExpr\SynArgPats.fs" />
|
<Compile Include="SynExpr\SynArgPats.fs" />
|
||||||
<Compile Include="SynExpr\SynField.fs" />
|
<Compile Include="SynExpr\SynField.fs" />
|
||||||
<Compile Include="SynExpr\SynUnionCase.fs" />
|
<Compile Include="SynExpr\SynUnionCase.fs" />
|
||||||
<Compile Include="SynExpr\SynPat.fs" />
|
<Compile Include="SynExpr\SynTypeDefnRepr.fs" />
|
||||||
|
<Compile Include="SynExpr\SynTypeDefn.fs" />
|
||||||
|
<Compile Include="SynExpr\SynComponentInfo.fs" />
|
||||||
|
<Compile Include="SynExpr\SynMemberDefn.fs" />
|
||||||
|
<Compile Include="SynExpr\SynAttribute.fs" />
|
||||||
|
<Compile Include="AstHelper.fs" />
|
||||||
<Compile Include="RemoveOptionsGenerator.fs"/>
|
<Compile Include="RemoveOptionsGenerator.fs"/>
|
||||||
<Compile Include="InterfaceMockGenerator.fs"/>
|
<Compile Include="InterfaceMockGenerator.fs"/>
|
||||||
<Compile Include="JsonSerializeGenerator.fs"/>
|
<Compile Include="JsonSerializeGenerator.fs"/>
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
":/",
|
":/",
|
||||||
":^WoofWare.Myriad.Plugins.Test/",
|
":^WoofWare.Myriad.Plugins.Test/",
|
||||||
":^WoofWare.Myriad.Plugins.Attributes/Test/",
|
":^WoofWare.Myriad.Plugins.Attributes/Test/",
|
||||||
":^/.github/"
|
":^/.github/",
|
||||||
|
":^/CHANGELOG.md"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user