mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-06 12:38:40 +00:00
Compare commits
1 Commits
WoofWare.M
...
WoofWare.M
Author | SHA1 | Date | |
---|---|---|---|
|
8e47f39efc |
@@ -8,8 +8,7 @@
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the InnerType type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module InnerType =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType =
|
||||
@@ -31,8 +30,7 @@ module InnerType =
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the JsonRecordType type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module JsonRecordType =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType =
|
||||
|
@@ -41,8 +41,7 @@ module MemberJsonSerializeExtension =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the GymOpeningHours type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module GymOpeningHours =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymOpeningHours =
|
||||
@@ -78,8 +77,7 @@ module GymOpeningHours =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the GymAccessOptions type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module GymAccessOptions =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAccessOptions =
|
||||
@@ -114,8 +112,7 @@ module GymAccessOptions =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the GymLocation type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module GymLocation =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymLocation =
|
||||
@@ -192,8 +189,7 @@ module GymLocation =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the GymAddress type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module GymAddress =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAddress =
|
||||
@@ -259,8 +255,7 @@ module GymAddress =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the Gym type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module Gym =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Gym =
|
||||
@@ -620,8 +615,7 @@ module MemberJsonParseExtension =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the GymAttendance type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module GymAttendance =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAttendance =
|
||||
@@ -743,8 +737,7 @@ module GymAttendance =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the MemberActivityDto type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module MemberActivityDto =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : MemberActivityDto =
|
||||
@@ -832,8 +825,7 @@ module MemberActivityDto =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the SessionsAggregate type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module SessionsAggregate =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
|
||||
@@ -881,8 +873,7 @@ module SessionsAggregate =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the VisitGym type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module VisitGym =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
|
||||
@@ -930,8 +921,7 @@ module VisitGym =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the Visit type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module Visit =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
|
||||
@@ -993,8 +983,7 @@ module Visit =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the SessionsSummary type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module SessionsSummary =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
|
||||
@@ -1029,8 +1018,7 @@ module SessionsSummary =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the Sessions type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module Sessions =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
|
||||
@@ -1066,8 +1054,7 @@ module Sessions =
|
||||
namespace PureGym
|
||||
|
||||
/// Module containing JSON parsing methods for the UriThing type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module UriThing =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing =
|
||||
|
@@ -17,8 +17,7 @@ open System.Net.Http
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
module PureGymApi =
|
||||
/// Create a REST client.
|
||||
let make (client : System.Net.Http.HttpClient) : IPureGymApi =
|
||||
@@ -1055,8 +1054,7 @@ open System.Net.Http
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
module internal ApiWithoutBaseAddress =
|
||||
/// Create a REST client.
|
||||
let make (client : System.Net.Http.HttpClient) : IApiWithoutBaseAddress =
|
||||
@@ -1107,8 +1105,7 @@ open System.Net.Http
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
module ApiWithBasePath =
|
||||
/// Create a REST client.
|
||||
let make (client : System.Net.Http.HttpClient) : IApiWithBasePath =
|
||||
@@ -1159,8 +1156,7 @@ open System.Net.Http
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
module ApiWithBasePathAndAddress =
|
||||
/// Create a REST client.
|
||||
let make (client : System.Net.Http.HttpClient) : IApiWithBasePathAndAddress =
|
||||
@@ -1205,8 +1201,7 @@ open System.Net.Http
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
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.
|
||||
let make
|
||||
@@ -1268,8 +1263,7 @@ open System.Net.Http
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
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.
|
||||
let make
|
||||
|
@@ -8,8 +8,7 @@
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the JwtVaultAuthResponse type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module JwtVaultAuthResponse =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultAuthResponse =
|
||||
@@ -164,8 +163,7 @@ module JwtVaultAuthResponse =
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the JwtVaultResponse type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module JwtVaultResponse =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultResponse =
|
||||
@@ -239,8 +237,7 @@ module JwtVaultResponse =
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the JwtSecretResponse type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module JwtSecretResponse =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtSecretResponse =
|
||||
@@ -455,8 +452,7 @@ open System.Threading.Tasks
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
module VaultClient =
|
||||
/// Create a REST client.
|
||||
let make (client : System.Net.Http.HttpClient) : IVaultClient =
|
||||
@@ -553,8 +549,7 @@ open System.Threading.Tasks
|
||||
open RestEase
|
||||
|
||||
/// Module for constructing a REST client.
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||
module VaultClientNonExtensionMethod =
|
||||
/// Create a REST client.
|
||||
let make (client : System.Net.Http.HttpClient) : IVaultClientNonExtensionMethod =
|
||||
|
@@ -1,7 +1,6 @@
|
||||
namespace WoofWare.Myriad.Plugins
|
||||
|
||||
open Fantomas.FCS.Syntax
|
||||
open Fantomas.FCS.SyntaxTrivia
|
||||
open Fantomas.FCS.Text.Range
|
||||
open Fantomas.FCS.Xml
|
||||
open Myriad.Core.AstExtensions
|
||||
@@ -98,30 +97,6 @@ type internal AdtProduct =
|
||||
[<RequireQualifiedAccess>]
|
||||
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 fields =
|
||||
fields
|
||||
@@ -130,86 +105,17 @@ module internal AstHelper =
|
||||
SynExpr.Record (None, None, fields, range0)
|
||||
|
||||
let defineRecordType (record : RecordType) : SynTypeDefn =
|
||||
let repr =
|
||||
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, Seq.toList record.Fields, range0), range0)
|
||||
|
||||
let name =
|
||||
SynComponentInfo.Create (
|
||||
[ record.Name ],
|
||||
?xmldoc = record.XmlDoc,
|
||||
?parameters = record.Generics,
|
||||
access = record.Accessibility
|
||||
)
|
||||
SynComponentInfo.create record.Name
|
||||
|> SynComponentInfo.setAccessibility record.Accessibility
|
||||
|> match record.XmlDoc with
|
||||
| None -> id
|
||||
| Some doc -> SynComponentInfo.withDocString doc
|
||||
|> SynComponentInfo.setGenerics record.Generics
|
||||
|
||||
let trivia : SynTypeDefnTrivia =
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
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
|
||||
SynTypeDefnRepr.record (Seq.toList record.Fields)
|
||||
|> SynTypeDefn.create name
|
||||
|> SynTypeDefn.withMemberDefns (defaultArg record.Members SynMemberDefns.Empty)
|
||||
|
||||
let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list =
|
||||
moduleDecls
|
||||
@@ -254,7 +160,7 @@ module internal AstHelper =
|
||||
Attributes = []
|
||||
IsOptional = false
|
||||
Id = None
|
||||
Type = SynType.Var (typar, range0)
|
||||
Type = SynType.var typar
|
||||
},
|
||||
false
|
||||
| _ -> failwithf "expected SignatureParameter, got: %+A" ty
|
||||
@@ -356,7 +262,7 @@ module internal AstHelper =
|
||||
Attributes = []
|
||||
IsOptional = false
|
||||
Id = None
|
||||
Type = SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent ident)
|
||||
Type = SynType.createLongIdent ident
|
||||
}
|
||||
|> List.singleton
|
||||
}
|
||||
@@ -368,7 +274,7 @@ module internal AstHelper =
|
||||
Attributes = []
|
||||
IsOptional = false
|
||||
Id = None
|
||||
Type = SynType.Var (typar, range0)
|
||||
Type = SynType.var typar
|
||||
}
|
||||
|> List.singleton
|
||||
}
|
||||
@@ -522,190 +428,3 @@ module internal AstHelper =
|
||||
}
|
||||
)
|
||||
| _ -> 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
|
||||
|
@@ -136,11 +136,11 @@ module internal CataGenerator =
|
||||
|
||||
let userProvidedTyparsForCase =
|
||||
analysis.Typars
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, ty)) -> SynType.Var (ty, range0))
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, ty)) -> SynType.var ty)
|
||||
|
||||
let userProvidedTyparsForCata =
|
||||
userProvidedTypars
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, ty)) -> SynType.Var (ty, range0))
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, ty)) -> SynType.var ty)
|
||||
|
||||
let relevantTyparName =
|
||||
match relevantTypar with
|
||||
@@ -148,48 +148,30 @@ module internal CataGenerator =
|
||||
| _ -> failwith "logic error in generator"
|
||||
|
||||
let inputObjectType =
|
||||
let baseType =
|
||||
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent relevantTypeName)
|
||||
let baseType = SynType.createLongIdent relevantTypeName
|
||||
|
||||
if userProvidedTypars.Length = 0 then
|
||||
baseType
|
||||
else
|
||||
SynType.App (
|
||||
baseType,
|
||||
Some range0,
|
||||
userProvidedTyparsForCase,
|
||||
List.replicate (userProvidedTypars.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
SynType.app' baseType userProvidedTyparsForCase
|
||||
|
||||
// The object on which we'll run the cata
|
||||
let inputObject =
|
||||
SynPat.CreateTyped (SynPat.CreateNamed (Ident.Create "x"), inputObjectType)
|
||||
let inputObject = SynPat.named "x" |> SynPat.annotateType inputObjectType
|
||||
|
||||
let cataObject =
|
||||
SynPat.CreateTyped (
|
||||
SynPat.CreateNamed (Ident.Create "cata"),
|
||||
SynType.App (
|
||||
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ cataName ]),
|
||||
Some range0,
|
||||
userProvidedTyparsForCata @ allArtificialTypars,
|
||||
List.replicate (userProvidedTypars.Length + allArtificialTypars.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
SynPat.named "cata"
|
||||
|> SynPat.annotateType (
|
||||
SynType.app' (SynType.createLongIdent [ cataName ]) (userProvidedTyparsForCata @ allArtificialTypars)
|
||||
)
|
||||
|
||||
[
|
||||
SynExpr.CreateLongIdent analysis.AssociatedProcessInstruction
|
||||
|> SynExpr.applyTo (SynExpr.CreateLongIdent (SynLongIdent.CreateString "x"))
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.applyTo (SynExpr.createLongIdent [ "x" ])
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "instructions" ; "Add" ])
|
||||
|
||||
// TODO: add the "all other stacks are empty" sanity checks
|
||||
SynExpr.CreateIdent (Ident.Create (relevantTyparName.idText + "Stack") |> Ident.lowerFirstLetter)
|
||||
SynExpr.createIdent' (Ident.create (relevantTyparName.idText + "Stack") |> Ident.lowerFirstLetter)
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "Seq" ; "exactlyOne" ])
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
@@ -209,26 +191,25 @@ module internal CataGenerator =
|
||||
range0
|
||||
),
|
||||
expr =
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateApp (SynExpr.CreateIdentString "loop", SynExpr.CreateIdentString "cata"),
|
||||
SynExpr.CreateIdentString "instructions"
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.applyFunction (SynExpr.createIdent "loop") (SynExpr.createIdent "cata"))
|
||||
(SynExpr.createIdent "instructions")
|
||||
)
|
||||
]
|
||||
]
|
||||
|> SynExpr.CreateSequential
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.CreateIdentString "ResizeArray"
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
|> SynBinding.basic (SynLongIdent.CreateString "instructions") []
|
||||
SynExpr.createIdent "ResizeArray"
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
|> SynBinding.basic (SynLongIdent.createS "instructions") []
|
||||
]
|
||||
|> SynExpr.typeAnnotate relevantTypar
|
||||
|> SynBinding.basic
|
||||
(SynLongIdent.CreateString ("run" + List.last(relevantTypeName).idText))
|
||||
[ SynPat.CreateParen cataObject ; SynPat.CreateParen inputObject ]
|
||||
(SynLongIdent.createS ("run" + List.last(relevantTypeName).idText))
|
||||
[ cataObject ; inputObject ]
|
||||
|> SynBinding.withReturnAnnotation relevantTypar
|
||||
|> SynBinding.withXmlDoc (PreXmlDoc.Create " Execute the catamorphism.")
|
||||
|> SynBinding.withXmlDoc (PreXmlDoc.create "Execute the catamorphism.")
|
||||
|
||||
let getName (ty : SynTypeDefn) : LongIdent =
|
||||
match ty with
|
||||
@@ -280,7 +261,7 @@ module internal CataGenerator =
|
||||
ArgName =
|
||||
match name with
|
||||
| Some n -> Ident.lowerFirstLetter n
|
||||
| None -> Ident.Create $"arg%s{prefix}"
|
||||
| None -> Ident.create $"arg%s{prefix}"
|
||||
Description = FieldDescription.Self ty
|
||||
RequiredGenerics = typeArgs
|
||||
}
|
||||
@@ -290,7 +271,7 @@ module internal CataGenerator =
|
||||
ArgName =
|
||||
match name with
|
||||
| Some n -> Ident.lowerFirstLetter n
|
||||
| None -> Ident.Create $"arg%s{prefix}"
|
||||
| None -> Ident.create $"arg%s{prefix}"
|
||||
Description = FieldDescription.NonRecursive ty
|
||||
RequiredGenerics = typeArgs
|
||||
}
|
||||
@@ -308,7 +289,7 @@ module internal CataGenerator =
|
||||
ArgName =
|
||||
match name with
|
||||
| Some n -> Ident.lowerFirstLetter n
|
||||
| None -> Ident.Create $"arg%s{prefix}"
|
||||
| None -> Ident.create $"arg%s{prefix}"
|
||||
Description = FieldDescription.NonRecursive stripped
|
||||
RequiredGenerics = typeArgs
|
||||
}
|
||||
@@ -318,7 +299,7 @@ module internal CataGenerator =
|
||||
ArgName =
|
||||
match name with
|
||||
| Some n -> Ident.lowerFirstLetter n
|
||||
| None -> Ident.Create $"arg%s{prefix}"
|
||||
| None -> Ident.create $"arg%s{prefix}"
|
||||
Description = FieldDescription.ListSelf ty
|
||||
RequiredGenerics = typeArgs
|
||||
}
|
||||
@@ -329,7 +310,7 @@ module internal CataGenerator =
|
||||
ArgName =
|
||||
match name with
|
||||
| Some n -> Ident.lowerFirstLetter n
|
||||
| None -> Ident.Create $"arg%s{prefix}"
|
||||
| None -> Ident.create $"arg%s{prefix}"
|
||||
Description = FieldDescription.NonRecursive stripped
|
||||
RequiredGenerics = typeArgs
|
||||
}
|
||||
@@ -357,7 +338,7 @@ module internal CataGenerator =
|
||||
ArgName =
|
||||
match name with
|
||||
| Some n -> Ident.lowerFirstLetter n
|
||||
| None -> Ident.Create $"arg%s{prefix}"
|
||||
| None -> Ident.create $"arg%s{prefix}"
|
||||
Description = FieldDescription.NonRecursive ty
|
||||
RequiredGenerics = typeArgs
|
||||
}
|
||||
@@ -391,7 +372,7 @@ module internal CataGenerator =
|
||||
let getInstructionCaseName (thisUnionType : SynTypeDefn) (caseName : SynIdent) : Ident =
|
||||
match caseName with
|
||||
| SynIdent.SynIdent (ident, _) ->
|
||||
(List.last (getName thisUnionType)).idText + "_" + ident.idText |> Ident.Create
|
||||
(List.last (getName thisUnionType)).idText + "_" + ident.idText |> Ident.create
|
||||
|
||||
/// Given the input `| Pair of Expr * Expr * PairOpKind`,
|
||||
/// strips out any members which contain recursive calls.
|
||||
@@ -449,25 +430,15 @@ module internal CataGenerator =
|
||||
{
|
||||
Name = None
|
||||
Type =
|
||||
let name =
|
||||
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent union.ParentTypeName)
|
||||
let name = SynType.createLongIdent union.ParentTypeName
|
||||
|
||||
match union.Typars with
|
||||
| [] -> name
|
||||
| typars ->
|
||||
let typars =
|
||||
typars
|
||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|
||||
let typars = typars |> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||
|
||||
SynType.app' name typars
|
||||
|
||||
SynType.App (
|
||||
name,
|
||||
Some range0,
|
||||
typars,
|
||||
List.replicate (typars.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
GenericsOfParent = union.Typars
|
||||
}
|
||||
|> List.singleton
|
||||
@@ -487,7 +458,7 @@ module internal CataGenerator =
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText)
|
||||
|> List.distinct
|
||||
|> List.map (fun i ->
|
||||
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false))
|
||||
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.create i, TyparStaticReq.None, false))
|
||||
)
|
||||
|
||||
// One union case for each union type, and then
|
||||
@@ -514,13 +485,9 @@ module internal CataGenerator =
|
||||
let cases = casesFromProcess @ casesFromCases
|
||||
|
||||
let typars =
|
||||
let count = analysis |> List.map (fun x -> List.length x.Typars) |> List.max
|
||||
|
||||
if analysis |> List.forall (fun x -> x.Typars.IsEmpty) then
|
||||
None
|
||||
[]
|
||||
else
|
||||
|
||||
let typars =
|
||||
analysis
|
||||
|> List.collect _.Typars
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText)
|
||||
@@ -529,28 +496,12 @@ module internal CataGenerator =
|
||||
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false))
|
||||
)
|
||||
|
||||
Some (SynTyparDecls.PostfixList (typars, [], range0))
|
||||
|
||||
SynTypeDefn.SynTypeDefn (
|
||||
SynComponentInfo.SynComponentInfo (
|
||||
[ SynAttributeList.Create [ SynAttribute.RequireQualifiedAccess () ] ],
|
||||
typars,
|
||||
[],
|
||||
[ Ident.Create "Instruction" ],
|
||||
PreXmlDoc.Empty,
|
||||
false,
|
||||
Some (SynAccess.Private range0),
|
||||
range0
|
||||
),
|
||||
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (None, cases, range0), range0),
|
||||
[],
|
||||
None,
|
||||
range0,
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
EqualsRange = Some range0
|
||||
WithKeyword = None
|
||||
}
|
||||
SynTypeDefnRepr.union cases
|
||||
|> SynTypeDefn.create (
|
||||
SynComponentInfo.create (Ident.create "Instruction")
|
||||
|> SynComponentInfo.withGenerics typars
|
||||
|> SynComponentInfo.withAccessibility (SynAccess.Private range0)
|
||||
|> SynComponentInfo.addAttributes [ SynAttribute.RequireQualifiedAccess () ]
|
||||
)
|
||||
|
||||
/// Build the cata interfaces, which a user will instantiate to specify a particular
|
||||
@@ -582,133 +533,54 @@ module internal CataGenerator =
|
||||
analyses
|
||||
|> List.map (fun analysis ->
|
||||
let componentInfo =
|
||||
SynComponentInfo.SynComponentInfo (
|
||||
[],
|
||||
Some (SynTyparDecls.PostfixList (analysis.Typars @ orderedGenerics, [], range0)),
|
||||
[],
|
||||
[ analysis.CataTypeName ],
|
||||
// TODO: better docstring
|
||||
PreXmlDoc.Create " Description of how to combine cases during a fold",
|
||||
false,
|
||||
None,
|
||||
range0
|
||||
SynComponentInfo.create analysis.CataTypeName
|
||||
// TODO: better docstring
|
||||
|> SynComponentInfo.withDocString (
|
||||
PreXmlDoc.create "Description of how to combine cases during a fold"
|
||||
)
|
||||
|> SynComponentInfo.withGenerics (analysis.Typars @ orderedGenerics)
|
||||
|
||||
let slots =
|
||||
let ourGenericName = generics.[analysis.GenericName.idText]
|
||||
|
||||
let flags =
|
||||
{
|
||||
SynMemberFlags.IsInstance = true
|
||||
SynMemberFlags.IsDispatchSlot = true
|
||||
SynMemberFlags.IsOverrideOrExplicitImpl = false
|
||||
SynMemberFlags.IsFinal = false
|
||||
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
||||
SynMemberFlags.MemberKind = SynMemberKind.Member
|
||||
}
|
||||
|
||||
analysis.UnionCases
|
||||
|> List.map (fun case ->
|
||||
let arity =
|
||||
SynValInfo.SynValInfo (
|
||||
case.Fields |> List.map (fun field -> [ SynArgInfo.Empty ]),
|
||||
SynArgInfo.Empty
|
||||
)
|
||||
|
||||
let ty =
|
||||
(SynType.Var (ourGenericName, range0), List.rev case.FlattenedFields)
|
||||
||> List.fold (fun acc field ->
|
||||
let place : SynType =
|
||||
match field.Description with
|
||||
| FieldDescription.Self ty -> SynType.Var (generics.[getNameKeyUnion ty], range0)
|
||||
| FieldDescription.ListSelf ty ->
|
||||
SynType.CreateApp (
|
||||
SynType.CreateLongIdent "list",
|
||||
[ SynType.Var (generics.[getNameKeyUnion ty], range0) ],
|
||||
true
|
||||
)
|
||||
| FieldDescription.NonRecursive ty ->
|
||||
match field.RequiredGenerics with
|
||||
| None -> ty
|
||||
| Some generics ->
|
||||
let generics =
|
||||
generics
|
||||
|> List.map (fun i ->
|
||||
let (SynTyparDecl.SynTyparDecl (_, typar)) = analysis.Typars.[i]
|
||||
SynType.Var (typar, range0)
|
||||
)
|
||||
|
||||
SynType.App (
|
||||
ty,
|
||||
Some range0,
|
||||
generics,
|
||||
List.replicate (generics.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
|
||||
SynType.Fun (
|
||||
SynType.SignatureParameter (
|
||||
[],
|
||||
false,
|
||||
field.FieldName |> Option.map Ident.lowerFirstLetter,
|
||||
place,
|
||||
range0
|
||||
),
|
||||
acc,
|
||||
range0,
|
||||
{
|
||||
ArrowRange = range0
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
let slot =
|
||||
SynValSig.SynValSig (
|
||||
[],
|
||||
case.CataMethodIdent,
|
||||
SynValTyparDecls.SynValTyparDecls (None, true),
|
||||
ty,
|
||||
arity,
|
||||
false,
|
||||
false,
|
||||
PreXmlDoc.Create $" How to operate on the %s{List.last(case.Match.LongIdent).idText} case",
|
||||
None,
|
||||
None,
|
||||
range0,
|
||||
{
|
||||
EqualsRange = None
|
||||
WithKeyword = None
|
||||
InlineKeyword = None
|
||||
LeadingKeyword = SynLeadingKeyword.Abstract range0
|
||||
}
|
||||
)
|
||||
|
||||
SynMemberDefn.AbstractSlot (
|
||||
slot,
|
||||
flags,
|
||||
range0,
|
||||
{
|
||||
GetSetKeywords = None
|
||||
}
|
||||
analysis.UnionCases
|
||||
|> List.map (fun case ->
|
||||
let arity =
|
||||
SynValInfo.SynValInfo (
|
||||
case.Fields |> List.map (fun field -> [ SynArgInfo.Empty ]),
|
||||
SynArgInfo.Empty
|
||||
)
|
||||
|
||||
(SynType.var generics.[analysis.GenericName.idText], List.rev case.FlattenedFields)
|
||||
||> List.fold (fun acc field ->
|
||||
let place : SynType =
|
||||
match field.Description with
|
||||
| FieldDescription.Self ty -> SynType.var generics.[getNameKeyUnion ty]
|
||||
| FieldDescription.ListSelf ty ->
|
||||
SynType.var generics.[getNameKeyUnion ty] |> SynType.appPostfix "list"
|
||||
| FieldDescription.NonRecursive ty ->
|
||||
match field.RequiredGenerics with
|
||||
| None -> ty
|
||||
| Some generics ->
|
||||
generics
|
||||
|> List.map (fun i ->
|
||||
let (SynTyparDecl.SynTyparDecl (_, typar)) = analysis.Typars.[i]
|
||||
SynType.var typar
|
||||
)
|
||||
|> SynType.app' ty
|
||||
|
||||
let domain =
|
||||
field.FieldName
|
||||
|> Option.map Ident.lowerFirstLetter
|
||||
|> SynType.signatureParamOfType place
|
||||
|
||||
acc |> SynType.funFromDomain domain
|
||||
)
|
||||
|
||||
let repr = SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Unspecified, slots, range0)
|
||||
|
||||
SynTypeDefn.SynTypeDefn (
|
||||
componentInfo,
|
||||
repr,
|
||||
[],
|
||||
None,
|
||||
range0,
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
EqualsRange = Some range0
|
||||
WithKeyword = None
|
||||
}
|
||||
|> SynMemberDefn.abstractMember
|
||||
case.CataMethodIdent
|
||||
None
|
||||
arity
|
||||
(PreXmlDoc.create $"How to operate on the %s{List.last(case.Match.LongIdent).idText} case")
|
||||
)
|
||||
|> SynTypeDefnRepr.interfaceType
|
||||
|> SynTypeDefn.create componentInfo
|
||||
)
|
||||
|
||||
/// Build a record which contains one of every cata type.
|
||||
@@ -727,28 +599,20 @@ module internal CataGenerator =
|
||||
let nameForDoc = List.last(analysis.ParentTypeName).idText
|
||||
|
||||
let doc =
|
||||
PreXmlDoc.Create $" How to perform a fold (catamorphism) over the type %s{nameForDoc}"
|
||||
PreXmlDoc.create $"How to perform a fold (catamorphism) over the type %s{nameForDoc}"
|
||||
|
||||
let artificialGenerics = generics |> List.map (fun v -> SynType.Var (v, range0))
|
||||
let artificialGenerics = generics |> List.map SynType.var
|
||||
|
||||
let userInputGenerics =
|
||||
analysis.Typars
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText)
|
||||
|> List.distinct
|
||||
|> List.map (fun i ->
|
||||
SynType.Var (SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false), range0)
|
||||
)
|
||||
|> List.map (fun i -> SynType.var (SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false)))
|
||||
|
||||
let ty =
|
||||
SynType.App (
|
||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent [ analysis.CataTypeName ]),
|
||||
Some range0,
|
||||
userInputGenerics @ artificialGenerics,
|
||||
List.replicate (generics.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
SynType.app'
|
||||
(SynType.createLongIdent [ analysis.CataTypeName ])
|
||||
(userInputGenerics @ artificialGenerics)
|
||||
|
||||
SynField.SynField (
|
||||
[],
|
||||
@@ -772,36 +636,18 @@ module internal CataGenerator =
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText)
|
||||
|> List.distinct
|
||||
|> List.map (fun i ->
|
||||
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false))
|
||||
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.create i, TyparStaticReq.None, false))
|
||||
)
|
||||
|
||||
let genericsFromCata =
|
||||
generics |> List.map (fun ty -> SynTyparDecl.SynTyparDecl ([], ty))
|
||||
|
||||
let componentInfo =
|
||||
SynComponentInfo.SynComponentInfo (
|
||||
[],
|
||||
Some (SynTyparDecls.PostfixList (genericsFromUserInput @ genericsFromCata, [], range0)),
|
||||
[],
|
||||
[ cataName ],
|
||||
doc,
|
||||
false,
|
||||
None,
|
||||
range0
|
||||
)
|
||||
SynComponentInfo.create cataName
|
||||
|> SynComponentInfo.withGenerics (genericsFromUserInput @ genericsFromCata)
|
||||
|> SynComponentInfo.withDocString doc
|
||||
|
||||
SynTypeDefn.SynTypeDefn (
|
||||
componentInfo,
|
||||
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, fields, range0), range0),
|
||||
[],
|
||||
None,
|
||||
range0,
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
WithKeyword = None
|
||||
EqualsRange = Some range0
|
||||
}
|
||||
)
|
||||
SynTypeDefnRepr.record fields |> SynTypeDefn.create componentInfo
|
||||
|
||||
let makeUnionAnalyses
|
||||
(cataVarName : Ident)
|
||||
@@ -852,7 +698,7 @@ module internal CataGenerator =
|
||||
Accessibility = access
|
||||
StackName =
|
||||
List.last(getName unionType).idText + "Stack"
|
||||
|> Ident.Create
|
||||
|> Ident.create
|
||||
|> Ident.lowerFirstLetter
|
||||
UnionCases =
|
||||
cases
|
||||
@@ -867,33 +713,30 @@ module internal CataGenerator =
|
||||
InstructionName = instructionName
|
||||
Fields = analysis
|
||||
CaseName = name
|
||||
CataMethodName =
|
||||
SynLongIdent.CreateFromLongIdent (cataVarName :: unionTypeName @ [ unionCaseName ])
|
||||
CataMethodName = SynLongIdent.create (cataVarName :: unionTypeName @ [ unionCaseName ])
|
||||
CataMethodIdent = SynIdent.SynIdent (unionCaseName, None)
|
||||
AssociatedInstruction =
|
||||
SynLongIdent.CreateFromLongIdent [ Ident.Create "Instruction" ; instructionName ]
|
||||
Match = SynLongIdent.CreateFromLongIdent (unionTypeName @ [ unionCaseName ])
|
||||
SynLongIdent.create [ Ident.create "Instruction" ; instructionName ]
|
||||
Match = SynLongIdent.create (unionTypeName @ [ unionCaseName ])
|
||||
}
|
||||
)
|
||||
AssociatedProcessInstruction =
|
||||
SynLongIdent.Create
|
||||
SynLongIdent.createS'
|
||||
[
|
||||
"Instruction"
|
||||
// such jank!
|
||||
"Process__" + List.last(unionTypeName).idText
|
||||
]
|
||||
ParentTypeName = getName unionType
|
||||
GenericName = getName unionType |> List.map _.idText |> String.concat "" |> Ident.Create
|
||||
CataTypeName = List.last(getName unionType).idText + "CataCase" |> Ident.Create
|
||||
GenericName = getName unionType |> List.map _.idText |> String.concat "" |> Ident.create
|
||||
CataTypeName = List.last(getName unionType).idText + "CataCase" |> Ident.create
|
||||
}
|
||||
)
|
||||
|
||||
let callCataAndPushResult (resultStackName : Ident) (unionCase : RenderedUnionCase) : SynExpr =
|
||||
(SynExpr.CreateLongIdent unionCase.CataMethodName, unionCase.FlattenedFields)
|
||||
||> List.fold (fun body caseDesc -> SynExpr.CreateApp (body, SynExpr.CreateIdent caseDesc.ArgName))
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (resultStackName :: [ Ident.Create "Add" ]))
|
||||
)
|
||||
||> List.fold (fun body caseDesc -> SynExpr.applyFunction body (SynExpr.createIdent' caseDesc.ArgName))
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent' (resultStackName :: [ Ident.Create "Add" ]))
|
||||
|
||||
/// Create the state-machine matches which deal with receiving the instruction
|
||||
/// to "process one of the user-specified DU cases, pushing recursion instructions onto
|
||||
@@ -934,21 +777,20 @@ module internal CataGenerator =
|
||||
listSelfArgs
|
||||
|> List.map (fun (i, argName, _) ->
|
||||
i,
|
||||
SynExpr.CreateParen (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "List" ; "length" ]),
|
||||
SynExpr.CreateIdent argName
|
||||
)
|
||||
SynExpr.paren (
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "List" ; "length" ])
|
||||
(SynExpr.createIdent' argName)
|
||||
)
|
||||
)
|
||||
|> List.append (
|
||||
nonRecursiveArgs |> List.map (fun (i, arg, _) -> i, SynExpr.CreateIdent arg)
|
||||
nonRecursiveArgs |> List.map (fun (i, arg, _) -> i, SynExpr.createIdent' arg)
|
||||
)
|
||||
|> List.sortBy fst
|
||||
|> List.map snd
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> SynExpr.applyFunction (SynExpr.CreateLongIdent unionCase.AssociatedInstruction)
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "instructions" ; "Add" ])
|
||||
|
||||
[
|
||||
@@ -967,34 +809,30 @@ module internal CataGenerator =
|
||||
DebugPointAtInOrTo.Yes range0,
|
||||
SeqExprOnly.SeqExprOnly false,
|
||||
true,
|
||||
SynPat.CreateNamed (SynIdent.SynIdent (Ident.Create "elt", None)),
|
||||
SynExpr.CreateIdent caseDesc.ArgName,
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "instructions" ; "Add" ]),
|
||||
SynExpr.CreateParen (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent analysis.AssociatedProcessInstruction,
|
||||
SynExpr.CreateIdentString "elt"
|
||||
)
|
||||
)
|
||||
),
|
||||
SynPat.named "elt",
|
||||
SynExpr.createIdent' caseDesc.ArgName,
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "instructions" ; "Add" ])
|
||||
(SynExpr.paren (
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.CreateLongIdent analysis.AssociatedProcessInstruction)
|
||||
(SynExpr.createIdent "elt")
|
||||
)),
|
||||
range0
|
||||
)
|
||||
| Self synType ->
|
||||
// And push the instruction to process each recursive call
|
||||
// onto the stack.
|
||||
yield
|
||||
SynExpr.CreateLongIdent (
|
||||
// TODO: use an AssociatedProcessInstruction instead
|
||||
SynLongIdent.Create
|
||||
[
|
||||
"Instruction"
|
||||
// TODO wonky domain
|
||||
"Process" + "__" + List.last(getNameUnion(synType).Value).idText
|
||||
]
|
||||
)
|
||||
|> SynExpr.applyTo (SynExpr.CreateIdent caseDesc.ArgName)
|
||||
|> SynExpr.CreateParen
|
||||
// TODO: use an AssociatedProcessInstruction instead
|
||||
SynExpr.createLongIdent
|
||||
[
|
||||
"Instruction"
|
||||
// TODO wonky domain
|
||||
"Process" + "__" + List.last(getNameUnion(synType).Value).idText
|
||||
]
|
||||
|> SynExpr.applyTo (SynExpr.createIdent' caseDesc.ArgName)
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "instructions" ; "Add" ])
|
||||
]
|
||||
|> SynExpr.CreateSequential
|
||||
@@ -1038,14 +876,14 @@ module internal CataGenerator =
|
||||
)
|
||||
)
|
||||
|
||||
let bodyMatch = SynExpr.CreateMatch (SynExpr.CreateIdentString "x", matchCases)
|
||||
let bodyMatch = SynExpr.createMatch (SynExpr.createIdent "x") matchCases
|
||||
|
||||
SynMatchClause.SynMatchClause (
|
||||
SynPat.LongIdent (
|
||||
analysis.AssociatedProcessInstruction,
|
||||
None,
|
||||
None,
|
||||
SynArgPats.create [ Ident.Create "x" ],
|
||||
SynArgPats.create [ Ident.create "x" ],
|
||||
None,
|
||||
range0
|
||||
),
|
||||
@@ -1119,22 +957,20 @@ module internal CataGenerator =
|
||||
// TODO: this is jank
|
||||
let stackName = inputStacks.[List.last(getNameUnion(synType).Value).idText]
|
||||
|
||||
SynExpr.minusN (SynLongIdent.CreateFromLongIdent [ stackName ; Ident.Create "Count" ]) 1
|
||||
|> SynExpr.CreateParen
|
||||
SynExpr.minusN (SynLongIdent.create [ stackName ; Ident.create "Count" ]) 1
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (
|
||||
SynExpr.createLongIdent' [ stackName ; Ident.Create "RemoveAt" ]
|
||||
SynExpr.createLongIdent' [ stackName ; Ident.create "RemoveAt" ]
|
||||
)
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.DotIndexedGet (
|
||||
SynExpr.CreateIdent stackName,
|
||||
SynExpr.minusN
|
||||
(SynLongIdent.CreateFromLongIdent [ stackName ; Ident.Create "Count" ])
|
||||
1,
|
||||
SynExpr.createIdent' stackName,
|
||||
SynExpr.minusN (SynLongIdent.create [ stackName ; Ident.create "Count" ]) 1,
|
||||
range0,
|
||||
range0
|
||||
)
|
||||
|> SynBinding.basic (SynLongIdent.CreateFromLongIdent [ field.ArgName ]) []
|
||||
|> SynBinding.basic (SynLongIdent.createI field.ArgName) []
|
||||
]
|
||||
|> Some
|
||||
| ListSelf synType ->
|
||||
@@ -1147,20 +983,18 @@ module internal CataGenerator =
|
||||
SynExpr.For (
|
||||
DebugPointAtFor.Yes range0,
|
||||
DebugPointAtInOrTo.Yes range0,
|
||||
Ident.Create "i",
|
||||
Ident.create "i",
|
||||
Some range0,
|
||||
SynExpr.minusN
|
||||
(SynLongIdent.CreateFromLongIdent [ stackName ; Ident.Create "Count" ])
|
||||
1,
|
||||
SynExpr.minusN (SynLongIdent.create [ stackName ; Ident.create "Count" ]) 1,
|
||||
false,
|
||||
SynExpr.minus
|
||||
(SynLongIdent.CreateFromLongIdent [ stackName ; Ident.Create "Count" ])
|
||||
(SynExpr.CreateIdent field.ArgName),
|
||||
(SynLongIdent.create [ stackName ; Ident.create "Count" ])
|
||||
(SynExpr.createIdent' field.ArgName),
|
||||
SynExpr.YieldOrReturn (
|
||||
(true, false),
|
||||
SynExpr.DotIndexedGet (
|
||||
SynExpr.CreateIdent stackName,
|
||||
SynExpr.CreateIdentString "i",
|
||||
SynExpr.createIdent' stackName,
|
||||
SynExpr.createIdent "i",
|
||||
range0,
|
||||
range0
|
||||
),
|
||||
@@ -1170,44 +1004,36 @@ module internal CataGenerator =
|
||||
),
|
||||
range0
|
||||
)
|
||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "seq")
|
||||
|> SynExpr.applyFunction (SynExpr.createIdent "seq")
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "Seq" ; "toList" ])
|
||||
|> SynBinding.basic (SynLongIdent.CreateFromLongIdent [ field.ArgName ]) []
|
||||
|> SynBinding.basic (SynLongIdent.createI field.ArgName) []
|
||||
|
||||
let shadowedIdent = Ident.Create (field.ArgName.idText + "_len")
|
||||
let shadowedIdent = Ident.create (field.ArgName.idText + "_len")
|
||||
|
||||
[
|
||||
SynExpr.minus
|
||||
(SynLongIdent.CreateFromLongIdent [ stackName ; Ident.Create "Count" ])
|
||||
(SynExpr.CreateIdent shadowedIdent)
|
||||
SynExpr.CreateIdent shadowedIdent
|
||||
(SynLongIdent.create [ stackName ; Ident.create "Count" ])
|
||||
(SynExpr.createIdent' shadowedIdent)
|
||||
SynExpr.createIdent' shadowedIdent
|
||||
]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> SynExpr.applyFunction (
|
||||
SynExpr.createLongIdent' [ stackName ; Ident.Create "RemoveRange" ]
|
||||
SynExpr.createLongIdent' [ stackName ; Ident.create "RemoveRange" ]
|
||||
)
|
||||
|> SynExpr.createLet [ vals ]
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynBinding.basic
|
||||
(SynLongIdent.CreateFromLongIdent [ shadowedIdent ])
|
||||
(SynLongIdent.createI shadowedIdent)
|
||||
[]
|
||||
(SynExpr.CreateIdent field.ArgName)
|
||||
(SynExpr.createIdent' field.ArgName)
|
||||
]
|
||||
|> Some
|
||||
)
|
||||
|
||||
SynMatchClause.SynMatchClause (
|
||||
pat,
|
||||
None,
|
||||
SynExpr.CreateSequential (populateArgs @ [ callCataAndPushResult analysis.StackName unionCase ]),
|
||||
range0,
|
||||
DebugPointAtTarget.Yes,
|
||||
{
|
||||
ArrowRange = Some range0
|
||||
BarRange = Some range0
|
||||
}
|
||||
)
|
||||
(populateArgs @ [ callCataAndPushResult analysis.StackName unionCase ])
|
||||
|> SynExpr.CreateSequential
|
||||
|> SynMatchClause.create pat
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1217,60 +1043,29 @@ module internal CataGenerator =
|
||||
|> List.collect _.Typars
|
||||
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText)
|
||||
|> List.distinct
|
||||
|> List.map (fun i -> SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false))
|
||||
|> List.map (fun i -> SynTypar.SynTypar (Ident.create i, TyparStaticReq.None, false))
|
||||
|
||||
let instructionsArrType =
|
||||
if not userSuppliedGenerics.IsEmpty then
|
||||
SynType.App (
|
||||
SynType.CreateLongIdent "Instruction",
|
||||
Some range0,
|
||||
userSuppliedGenerics |> List.map (fun x -> SynType.Var (x, range0)),
|
||||
List.replicate (userSuppliedGenerics.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
userSuppliedGenerics |> List.map SynType.var |> SynType.app "Instruction"
|
||||
else
|
||||
SynType.CreateLongIdent "Instruction"
|
||||
SynType.named "Instruction"
|
||||
|
||||
let cataGenerics =
|
||||
[
|
||||
for generic in userSuppliedGenerics do
|
||||
yield SynType.Var (generic, range0)
|
||||
yield SynType.var generic
|
||||
for case in analysis do
|
||||
yield SynType.Var (SynTypar.SynTypar (case.GenericName, TyparStaticReq.None, false), range0)
|
||||
yield SynType.var (SynTypar.SynTypar (case.GenericName, TyparStaticReq.None, false))
|
||||
]
|
||||
|
||||
let args =
|
||||
[
|
||||
SynPat.CreateParen (
|
||||
SynPat.CreateTyped (
|
||||
SynPat.CreateNamed cataVarName,
|
||||
SynType.App (
|
||||
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ cataTypeName ]),
|
||||
Some range0,
|
||||
cataGenerics,
|
||||
List.replicate (cataGenerics.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
)
|
||||
)
|
||||
SynPat.CreateParen (
|
||||
SynPat.CreateTyped (
|
||||
SynPat.CreateNamed (Ident.Create "instructions"),
|
||||
SynType.App (
|
||||
SynType.CreateLongIdent "ResizeArray",
|
||||
Some range0,
|
||||
[ instructionsArrType ],
|
||||
[],
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
)
|
||||
)
|
||||
SynPat.namedI cataVarName
|
||||
|> SynPat.annotateType (SynType.app' (SynType.createLongIdent [ cataTypeName ]) cataGenerics)
|
||||
|
||||
SynPat.named "instructions"
|
||||
|> SynPat.annotateType (SynType.app "ResizeArray" [ instructionsArrType ])
|
||||
]
|
||||
|
||||
let baseMatchClauses = analysis |> List.map createBaseMatchClause
|
||||
@@ -1278,39 +1073,35 @@ module internal CataGenerator =
|
||||
let recMatchClauses = createRecursiveMatchClauses analysis
|
||||
|
||||
let matchStatement =
|
||||
SynExpr.CreateMatch (SynExpr.CreateIdentString "currentInstruction", baseMatchClauses @ recMatchClauses)
|
||||
SynExpr.createMatch (SynExpr.createIdent "currentInstruction") (baseMatchClauses @ recMatchClauses)
|
||||
|
||||
let body =
|
||||
[
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "instructions" ; "RemoveAt" ],
|
||||
SynExpr.CreateParen (SynExpr.minusN (SynLongIdent.Create [ "instructions" ; "Count" ]) 1)
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "instructions" ; "RemoveAt" ])
|
||||
(SynExpr.paren (SynExpr.minusN (SynLongIdent.createS' [ "instructions" ; "Count" ]) 1))
|
||||
matchStatement
|
||||
]
|
||||
|> SynExpr.CreateSequential
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.DotIndexedGet (
|
||||
SynExpr.CreateIdentString "instructions",
|
||||
SynExpr.minusN (SynLongIdent.Create [ "instructions" ; "Count" ]) 1,
|
||||
SynExpr.createIdent "instructions",
|
||||
SynExpr.minusN (SynLongIdent.createS' [ "instructions" ; "Count" ]) 1,
|
||||
range0,
|
||||
range0
|
||||
)
|
||||
|> SynBinding.basic (SynLongIdent.CreateString "currentInstruction") []
|
||||
|> SynBinding.basic (SynLongIdent.createS "currentInstruction") []
|
||||
]
|
||||
|
||||
let body =
|
||||
SynExpr.CreateSequential
|
||||
[
|
||||
SynExpr.While (
|
||||
DebugPointAtWhile.Yes range0,
|
||||
SynExpr.greaterThan
|
||||
(SynExpr.CreateConst (SynConst.Int32 0))
|
||||
(SynExpr.createLongIdent [ "instructions" ; "Count" ]),
|
||||
body,
|
||||
range0
|
||||
)
|
||||
SynExpr.createWhile
|
||||
(SynExpr.greaterThan
|
||||
(SynExpr.CreateConst 0)
|
||||
(SynExpr.createLongIdent [ "instructions" ; "Count" ]))
|
||||
body
|
||||
SynExpr.CreateTuple (
|
||||
analysis
|
||||
|> List.map (fun unionAnalysis -> [ unionAnalysis.StackName ] |> SynExpr.createLongIdent')
|
||||
@@ -1324,25 +1115,22 @@ module internal CataGenerator =
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.TypeApp (
|
||||
SynExpr.CreateIdent (Ident.Create "ResizeArray"),
|
||||
SynExpr.createIdent "ResizeArray",
|
||||
range0,
|
||||
[
|
||||
SynType.Var (
|
||||
SynTypar.SynTypar (unionCase.GenericName, TyparStaticReq.None, false),
|
||||
range0
|
||||
)
|
||||
SynType.var (SynTypar.SynTypar (unionCase.GenericName, TyparStaticReq.None, false))
|
||||
],
|
||||
[],
|
||||
Some range0,
|
||||
range0,
|
||||
range0
|
||||
)
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
|> SynBinding.basic (SynLongIdent.CreateFromLongIdent [ unionCase.StackName ]) []
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
|> SynBinding.basic (SynLongIdent.createI unionCase.StackName) []
|
||||
]
|
||||
)
|
||||
|
||||
SynBinding.basic (SynLongIdent.CreateString "loop") args body
|
||||
SynBinding.basic (SynLongIdent.createS "loop") args body
|
||||
|> SynBinding.withAccessibility (Some (SynAccess.Private range0))
|
||||
|
||||
let createModule
|
||||
@@ -1355,22 +1143,20 @@ module internal CataGenerator =
|
||||
=
|
||||
let cataName =
|
||||
match cataName |> SynExpr.stripOptionalParen with
|
||||
| SynExpr.Const (SynConst.String (name, _, _), _) -> Ident.Create name
|
||||
| SynExpr.Const (SynConst.String (name, _, _), _) -> Ident.create name
|
||||
| _ -> failwith "Cata name in attribute must be literally a string, sorry"
|
||||
|
||||
let parentName = List.last (getName taggedType) |> _.idText
|
||||
let moduleName : LongIdent = parentName + "Cata" |> Ident.Create |> List.singleton
|
||||
|
||||
let attribs = [ SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ()) ]
|
||||
let moduleName = parentName + "Cata" |> Ident.create
|
||||
|
||||
let modInfo =
|
||||
SynComponentInfo.Create (
|
||||
moduleName,
|
||||
attributes = attribs,
|
||||
xmldoc = PreXmlDoc.Create $" Methods to perform a catamorphism over the type %s{parentName}"
|
||||
SynComponentInfo.create (parentName + "Cata" |> Ident.create)
|
||||
|> SynComponentInfo.withDocString (
|
||||
PreXmlDoc.Create $" Methods to perform a catamorphism over the type %s{parentName}"
|
||||
)
|
||||
|> SynComponentInfo.addAttributes [ SynAttribute.RequireQualifiedAccess () ]
|
||||
|
||||
let cataVarName = Ident.Create "cata"
|
||||
let cataVarName = Ident.create "cata"
|
||||
let analysis = makeUnionAnalyses cataVarName allRecordTypes allUnionTypes
|
||||
|
||||
let allTypars =
|
||||
@@ -1378,9 +1164,9 @@ module internal CataGenerator =
|
||||
|> List.map (fun unionType ->
|
||||
List.last (getName unionType)
|
||||
|> fun x -> x.idText + "Ret"
|
||||
|> Ident.Create
|
||||
|> Ident.create
|
||||
|> fun x -> SynTypar.SynTypar (x, TyparStaticReq.None, false)
|
||||
|> fun x -> SynType.Var (x, range0)
|
||||
|> SynType.var
|
||||
)
|
||||
|
||||
let userProvidedGenerics =
|
||||
@@ -1389,7 +1175,7 @@ module internal CataGenerator =
|
||||
|> List.map (fun (SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText)
|
||||
|> List.distinct
|
||||
|> List.map (fun x ->
|
||||
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.Create x, TyparStaticReq.None, false))
|
||||
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.create x, TyparStaticReq.None, false))
|
||||
)
|
||||
|
||||
let runFunctions =
|
||||
@@ -1405,8 +1191,8 @@ module internal CataGenerator =
|
||||
let loopFunction = createLoopFunction cataName cataVarName analysis
|
||||
|
||||
let recordDoc =
|
||||
PreXmlDoc.Create
|
||||
$" Specifies how to perform a fold (catamorphism) over the type %s{parentName} and its friends."
|
||||
PreXmlDoc.create
|
||||
$"Specifies how to perform a fold (catamorphism) over the type %s{parentName} and its friends."
|
||||
|
||||
let cataRecord =
|
||||
SynModuleDecl.Types ([ createCataRecord cataName recordDoc analysis ], range0)
|
||||
|
@@ -213,11 +213,7 @@ module internal HttpClientGenerator =
|
||||
|
||||
let argType =
|
||||
if arg.IsOptional then
|
||||
SynType.CreateApp (
|
||||
SynType.CreateLongIdent (SynLongIdent.CreateString "option"),
|
||||
[ arg.Type ],
|
||||
isPostfix = true
|
||||
)
|
||||
SynType.appPostfix "option" arg.Type
|
||||
else
|
||||
arg.Type
|
||||
|
||||
@@ -241,7 +237,7 @@ module internal HttpClientGenerator =
|
||||
let thisIdent = if variableHeaders.IsEmpty then "_" else "this"
|
||||
|
||||
SynPat.LongIdent (
|
||||
SynLongIdent.CreateFromLongIdent [ Ident.Create thisIdent ; info.Identifier ],
|
||||
SynLongIdent.create [ Ident.create thisIdent ; info.Identifier ],
|
||||
None,
|
||||
None,
|
||||
argPats,
|
||||
@@ -271,7 +267,7 @@ module internal HttpClientGenerator =
|
||||
"Replace"
|
||||
(SynExpr.CreateParenedTuple
|
||||
[
|
||||
SynExpr.CreateConstString ("{" + substituteId + "}")
|
||||
SynExpr.CreateConst ("{" + substituteId + "}")
|
||||
SynExpr.callMethod "ToString" (SynExpr.CreateIdent varName)
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
||||
@@ -314,30 +310,27 @@ module internal HttpClientGenerator =
|
||||
let urlSeparator =
|
||||
// apparent Myriad bug: `IndexOf '?'` gets formatted as `IndexOf ?` which is clearly wrong
|
||||
let questionMark =
|
||||
SynExpr.CreateConst (SynConst.Int32 63)
|
||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "char")
|
||||
|> SynExpr.CreateParen
|
||||
SynExpr.CreateConst 63
|
||||
|> SynExpr.applyFunction (SynExpr.createIdent "char")
|
||||
|> SynExpr.paren
|
||||
|
||||
let containsQuestion =
|
||||
info.UrlTemplate
|
||||
|> SynExpr.callMethodArg "IndexOf" questionMark
|
||||
|> SynExpr.greaterThanOrEqual (SynExpr.CreateConst (SynConst.Int32 0))
|
||||
|> SynExpr.greaterThanOrEqual (SynExpr.CreateConst 0)
|
||||
|
||||
SynExpr.ifThenElse
|
||||
containsQuestion
|
||||
(SynExpr.CreateConst (SynConst.CreateString "?"))
|
||||
(SynExpr.CreateConst (SynConst.CreateString "&"))
|
||||
|> SynExpr.CreateParen
|
||||
SynExpr.ifThenElse containsQuestion (SynExpr.CreateConst "?") (SynExpr.CreateConst "&")
|
||||
|> SynExpr.paren
|
||||
|
||||
let prefix =
|
||||
SynExpr.CreateIdent firstValueId
|
||||
SynExpr.createIdent' firstValueId
|
||||
|> SynExpr.toString firstValue.Type
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ])
|
||||
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.plus (SynExpr.plus urlSeparator (SynExpr.CreateConstString (firstKey + "=")))
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.plus (SynExpr.plus urlSeparator (SynExpr.CreateConst (firstKey + "=")))
|
||||
|
||||
(prefix, queryParams)
|
||||
||> List.fold (fun uri (paramKey, paramValue) ->
|
||||
@@ -346,16 +339,16 @@ module internal HttpClientGenerator =
|
||||
| None -> failwith "Unable to get parameter variable name from anonymous parameter"
|
||||
| Some id -> id
|
||||
|
||||
SynExpr.toString paramValue.Type (SynExpr.CreateIdent paramValueId)
|
||||
|> SynExpr.CreateParen
|
||||
SynExpr.toString paramValue.Type (SynExpr.createIdent' paramValueId)
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.createLongIdent [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.plus (SynExpr.plus uri (SynExpr.CreateConstString ("&" + paramKey + "=")))
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.plus (SynExpr.plus uri (SynExpr.CreateConst ("&" + paramKey + "=")))
|
||||
)
|
||||
|> SynExpr.plus requestUriTrailer
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.paren
|
||||
|
||||
let requestUri =
|
||||
let uriIdent = SynExpr.createLongIdent [ "System" ; "Uri" ]
|
||||
@@ -370,20 +363,20 @@ module internal HttpClientGenerator =
|
||||
match info.BaseAddress with
|
||||
| None ->
|
||||
[
|
||||
SynExpr.CreateApp (SynExpr.CreateIdentString "nameof", SynExpr.CreateParen baseAddress)
|
||||
SynExpr.CreateConstString
|
||||
SynExpr.applyFunction (SynExpr.createIdent "nameof") (SynExpr.paren baseAddress)
|
||||
SynExpr.CreateConst
|
||||
"No base address was supplied on the type, and no BaseAddress was on the HttpClient."
|
||||
]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "ArgumentNullException" ])
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "raise")
|
||||
| Some expr -> SynExpr.CreateApp (uriIdent, expr)
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||
| Some expr -> SynExpr.applyFunction uriIdent expr
|
||||
)
|
||||
SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, SynExpr.CreateIdentString "v")
|
||||
SynMatchClause.Create (SynPat.named "v", None, SynExpr.createIdent "v")
|
||||
]
|
||||
|> SynExpr.createMatch baseAddress
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.paren
|
||||
|
||||
SynExpr.App (
|
||||
ExprAtomicFlag.Atomic,
|
||||
@@ -436,56 +429,43 @@ module internal HttpClientGenerator =
|
||||
let httpReqMessageConstructor =
|
||||
[
|
||||
SynExpr.equals
|
||||
(SynExpr.CreateIdentString "Method")
|
||||
(SynExpr.createIdent "Method")
|
||||
(SynExpr.createLongIdent
|
||||
[ "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.CreateTuple
|
||||
|
||||
let returnExpr =
|
||||
match info.TaskReturnType with
|
||||
| HttpResponseMessage -> SynExpr.CreateIdentString "response"
|
||||
| String -> SynExpr.CreateIdentString "responseString"
|
||||
| Stream -> SynExpr.CreateIdentString "responseStream"
|
||||
| HttpResponseMessage -> SynExpr.createIdent "response"
|
||||
| String -> SynExpr.createIdent "responseString"
|
||||
| Stream -> SynExpr.createIdent "responseStream"
|
||||
| RestEaseResponseType contents ->
|
||||
let deserialiser =
|
||||
SynExpr.CreateLambda (
|
||||
[ SynPat.CreateConst SynConst.Unit ],
|
||||
SynExpr.CreateParen (
|
||||
JsonParseGenerator.parseNode
|
||||
None
|
||||
JsonParseGenerator.JsonParseOption.None
|
||||
contents
|
||||
(SynExpr.CreateIdentString "jsonNode")
|
||||
)
|
||||
)
|
||||
JsonParseGenerator.parseNode
|
||||
None
|
||||
JsonParseGenerator.JsonParseOption.None
|
||||
contents
|
||||
(SynExpr.createIdent "jsonNode")
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.createThunk
|
||||
|
||||
// new RestEase.Response (content : string, response : HttpResponseMessage, deserialiser : unit -> 'T)
|
||||
SynExpr.New (
|
||||
false,
|
||||
SynType.App (
|
||||
SynType.CreateLongIdent (SynLongIdent.Create [ "RestEase" ; "Response" ]),
|
||||
Some range0,
|
||||
[ SynType.Anon range0 ],
|
||||
[],
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateParenedTuple
|
||||
SynExpr.createNew
|
||||
(SynType.app' (SynType.createLongIdent' [ "RestEase" ; "Response" ]) [ SynType.Anon range0 ])
|
||||
(SynExpr.CreateTuple
|
||||
[
|
||||
SynExpr.CreateIdentString "responseString"
|
||||
SynExpr.CreateIdentString "response"
|
||||
SynExpr.CreateParen deserialiser
|
||||
],
|
||||
range0
|
||||
)
|
||||
SynExpr.createIdent "responseString"
|
||||
SynExpr.createIdent "response"
|
||||
deserialiser
|
||||
])
|
||||
| retType ->
|
||||
JsonParseGenerator.parseNode
|
||||
None
|
||||
JsonParseGenerator.JsonParseOption.None
|
||||
retType
|
||||
(SynExpr.CreateIdentString "jsonNode")
|
||||
(SynExpr.createIdent "jsonNode")
|
||||
|
||||
let handleBodyParams =
|
||||
match bodyParam with
|
||||
@@ -498,20 +478,15 @@ module internal HttpClientGenerator =
|
||||
[
|
||||
Let (
|
||||
"queryParams",
|
||||
SynExpr.New (
|
||||
false,
|
||||
SynType.CreateLongIdent (
|
||||
SynLongIdent.Create
|
||||
[ "System" ; "Net" ; "Http" ; (bodyParamType : BodyParamMethods).ToString () ]
|
||||
),
|
||||
SynExpr.CreateParen (SynExpr.CreateIdent bodyParamName),
|
||||
range0
|
||||
)
|
||||
SynExpr.createNew
|
||||
(SynType.createLongIdent'
|
||||
[ "System" ; "Net" ; "Http" ; (bodyParamType : BodyParamMethods).ToString () ])
|
||||
(SynExpr.createIdent' bodyParamName)
|
||||
)
|
||||
Do (
|
||||
SynExpr.LongIdentSet (
|
||||
SynLongIdent.Create [ "httpMessage" ; "Content" ],
|
||||
SynExpr.CreateIdentString "queryParams",
|
||||
SynLongIdent.createS' [ "httpMessage" ; "Content" ],
|
||||
SynExpr.createIdent "queryParams",
|
||||
range0
|
||||
)
|
||||
)
|
||||
@@ -520,8 +495,8 @@ module internal HttpClientGenerator =
|
||||
[
|
||||
Do (
|
||||
SynExpr.LongIdentSet (
|
||||
SynLongIdent.Create [ "httpMessage" ; "Content" ],
|
||||
SynExpr.CreateIdent bodyParamName,
|
||||
SynLongIdent.createS' [ "httpMessage" ; "Content" ],
|
||||
SynExpr.createIdent' bodyParamName,
|
||||
range0
|
||||
)
|
||||
)
|
||||
@@ -530,38 +505,27 @@ module internal HttpClientGenerator =
|
||||
[
|
||||
Let (
|
||||
"queryParams",
|
||||
SynExpr.New (
|
||||
false,
|
||||
SynType.CreateLongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Net" ; "Http" ; "StringContent" ]
|
||||
),
|
||||
SynExpr.CreateParen (
|
||||
SynExpr.CreateIdent bodyParamName
|
||||
|> SynExpr.pipeThroughFunction (JsonSerializeGenerator.serializeNode ty)
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.createLambda
|
||||
"node"
|
||||
(SynExpr.ifThenElse
|
||||
(SynExpr.CreateApp (
|
||||
SynExpr.CreateIdentString "isNull",
|
||||
SynExpr.CreateIdentString "node"
|
||||
))
|
||||
(SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (
|
||||
SynLongIdent.Create [ "node" ; "ToJsonString" ]
|
||||
),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
))
|
||||
(SynExpr.CreateConst (SynConst.CreateString "null")))
|
||||
)
|
||||
),
|
||||
range0
|
||||
)
|
||||
SynExpr.createNew
|
||||
(SynType.createLongIdent' [ "System" ; "Net" ; "Http" ; "StringContent" ])
|
||||
(SynExpr.createIdent' bodyParamName
|
||||
|> SynExpr.pipeThroughFunction (JsonSerializeGenerator.serializeNode ty)
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.createLambda
|
||||
"node"
|
||||
(SynExpr.ifThenElse
|
||||
(SynExpr.applyFunction
|
||||
(SynExpr.createIdent "isNull")
|
||||
(SynExpr.createIdent "node"))
|
||||
(SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "node" ; "ToJsonString" ])
|
||||
(SynExpr.CreateConst ()))
|
||||
(SynExpr.CreateConst "null"))
|
||||
))
|
||||
)
|
||||
Do (
|
||||
SynExpr.LongIdentSet (
|
||||
SynLongIdent.Create [ "httpMessage" ; "Content" ],
|
||||
SynExpr.CreateIdent (Ident.Create "queryParams"),
|
||||
SynLongIdent.createS' [ "httpMessage" ; "Content" ],
|
||||
SynExpr.createIdent "queryParams",
|
||||
range0
|
||||
)
|
||||
)
|
||||
@@ -572,10 +536,9 @@ module internal HttpClientGenerator =
|
||||
LetBang (
|
||||
"responseString",
|
||||
SynExpr.awaitTask (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStringAsync" ],
|
||||
SynExpr.CreateIdentString "ct"
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStringAsync" ])
|
||||
(SynExpr.createIdent "ct")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -583,10 +546,9 @@ module internal HttpClientGenerator =
|
||||
LetBang (
|
||||
"responseStream",
|
||||
SynExpr.awaitTask (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStreamAsync" ],
|
||||
SynExpr.CreateIdentString "ct"
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "response" ; "Content" ; "ReadAsStreamAsync" ])
|
||||
(SynExpr.createIdent "ct")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -594,47 +556,39 @@ module internal HttpClientGenerator =
|
||||
LetBang (
|
||||
"jsonNode",
|
||||
SynExpr.awaitTask (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ; "ParseAsync" ],
|
||||
SynExpr.CreateParenedTuple
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent
|
||||
[ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ; "ParseAsync" ])
|
||||
(SynExpr.CreateParenedTuple
|
||||
[
|
||||
SynExpr.CreateIdentString "responseStream"
|
||||
SynExpr.equals
|
||||
(SynExpr.CreateIdentString "cancellationToken")
|
||||
(SynExpr.CreateIdentString "ct")
|
||||
]
|
||||
)
|
||||
SynExpr.createIdent "responseStream"
|
||||
SynExpr.equals (SynExpr.createIdent "cancellationToken") (SynExpr.createIdent "ct")
|
||||
])
|
||||
)
|
||||
)
|
||||
|
||||
let setVariableHeaders =
|
||||
variableHeaders
|
||||
|> List.map (fun (headerName, callToGetValue) ->
|
||||
Do (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ],
|
||||
SynExpr.CreateParenedTuple
|
||||
[
|
||||
headerName
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent'
|
||||
[ Ident.Create "this" ; callToGetValue ; Ident.Create "ToString" ],
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
[
|
||||
headerName
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent'
|
||||
[ Ident.Create "this" ; callToGetValue ; Ident.Create "ToString" ])
|
||||
(SynExpr.CreateConst ())
|
||||
]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ])
|
||||
|> Do
|
||||
)
|
||||
|
||||
let setConstantHeaders =
|
||||
constantHeaders
|
||||
|> List.map (fun (headerName, headerValue) ->
|
||||
Do (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ],
|
||||
SynExpr.CreateParenedTuple [ headerName ; headerValue ]
|
||||
)
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "httpMessage" ; "Headers" ; "Add" ])
|
||||
(SynExpr.CreateParenedTuple [ headerName ; headerValue ])
|
||||
|> Do
|
||||
)
|
||||
|
||||
[
|
||||
@@ -643,14 +597,9 @@ module internal HttpClientGenerator =
|
||||
yield
|
||||
Use (
|
||||
"httpMessage",
|
||||
SynExpr.New (
|
||||
false,
|
||||
SynType.CreateLongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Net" ; "Http" ; "HttpRequestMessage" ]
|
||||
),
|
||||
httpReqMessageConstructor,
|
||||
range0
|
||||
)
|
||||
SynExpr.createNew
|
||||
(SynType.createLongIdent' [ "System" ; "Net" ; "Http" ; "HttpRequestMessage" ])
|
||||
httpReqMessageConstructor
|
||||
)
|
||||
|
||||
yield! handleBodyParams
|
||||
@@ -662,21 +611,19 @@ module internal HttpClientGenerator =
|
||||
LetBang (
|
||||
"response",
|
||||
SynExpr.awaitTask (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "client" ; "SendAsync" ],
|
||||
SynExpr.CreateParenedTuple
|
||||
[ SynExpr.CreateIdentString "httpMessage" ; SynExpr.CreateIdentString "ct" ]
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "client" ; "SendAsync" ])
|
||||
(SynExpr.CreateParenedTuple
|
||||
[ SynExpr.createIdent "httpMessage" ; SynExpr.createIdent "ct" ])
|
||||
)
|
||||
)
|
||||
if info.EnsureSuccessHttpCode then
|
||||
yield
|
||||
Let (
|
||||
"response",
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "response" ; "EnsureSuccessStatusCode" ],
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "response" ; "EnsureSuccessStatusCode" ])
|
||||
(SynExpr.CreateConst ())
|
||||
)
|
||||
match info.TaskReturnType with
|
||||
| HttpResponseMessage -> ()
|
||||
@@ -691,7 +638,7 @@ module internal HttpClientGenerator =
|
||||
yield jsonNode
|
||||
]
|
||||
|> SynExpr.createCompExpr "async" returnExpr
|
||||
|> SynExpr.startAsTask (SynLongIdent.CreateFromLongIdent [ cancellationTokenArg ])
|
||||
|> SynExpr.startAsTask (SynLongIdent.createI cancellationTokenArg)
|
||||
|
||||
SynBinding.SynBinding (
|
||||
None,
|
||||
@@ -904,15 +851,11 @@ module internal HttpClientGenerator =
|
||||
SynValInfo.SynValInfo ([ [ SynArgInfo.Empty ] ; [] ], SynArgInfo.Empty),
|
||||
None
|
||||
),
|
||||
SynPat.CreateLongIdent (
|
||||
SynLongIdent.CreateFromLongIdent [ Ident.Create "_" ; pi.Identifier ],
|
||||
[]
|
||||
),
|
||||
SynPat.CreateLongIdent (SynLongIdent.create [ Ident.create "_" ; pi.Identifier ], []),
|
||||
Some (SynBindingReturnInfo.Create pi.Type),
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent' [ Ident.lowerFirstLetter pi.Identifier ],
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
),
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent' [ Ident.lowerFirstLetter pi.Identifier ])
|
||||
(SynExpr.CreateConst ()),
|
||||
range0,
|
||||
DebugPointAtBinding.Yes range0,
|
||||
{
|
||||
@@ -932,12 +875,12 @@ module internal HttpClientGenerator =
|
||||
"Extension methods"
|
||||
else
|
||||
"Module")
|
||||
|> sprintf " %s for constructing a REST client."
|
||||
|> PreXmlDoc.Create
|
||||
|> sprintf "%s for constructing a REST client."
|
||||
|> PreXmlDoc.create
|
||||
|
||||
let interfaceImpl =
|
||||
SynExpr.ObjExpr (
|
||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name),
|
||||
SynType.createLongIdent interfaceType.Name,
|
||||
None,
|
||||
Some range0,
|
||||
[],
|
||||
@@ -950,28 +893,22 @@ module internal HttpClientGenerator =
|
||||
let headerArgs =
|
||||
properties
|
||||
|> List.map (fun (_, pi) ->
|
||||
SynPat.CreateTyped (
|
||||
SynPat.CreateNamed (Ident.lowerFirstLetter pi.Identifier),
|
||||
SynType.CreateFun (SynType.CreateLongIdent "unit", pi.Type)
|
||||
)
|
||||
|> SynPat.CreateParen
|
||||
SynPat.namedI (Ident.lowerFirstLetter pi.Identifier)
|
||||
|> SynPat.annotateType (SynType.funFromDomain (SynType.named "unit") pi.Type)
|
||||
)
|
||||
|
||||
let clientCreationArg =
|
||||
SynPat.CreateTyped (
|
||||
SynPat.CreateNamed (Ident.Create "client"),
|
||||
SynType.CreateLongIdent (SynLongIdent.Create [ "System" ; "Net" ; "Http" ; "HttpClient" ])
|
||||
)
|
||||
|> SynPat.CreateParen
|
||||
SynPat.named "client"
|
||||
|> SynPat.annotateType (SynType.createLongIdent' [ "System" ; "Net" ; "Http" ; "HttpClient" ])
|
||||
|
||||
let xmlDoc =
|
||||
if properties.IsEmpty then
|
||||
" Create a REST client."
|
||||
"Create a REST client."
|
||||
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."
|
||||
|> PreXmlDoc.Create
|
||||
"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
|
||||
|
||||
let functionName = Ident.Create "client"
|
||||
let functionName = Ident.create "client"
|
||||
|
||||
let valData =
|
||||
let memberFlags =
|
||||
@@ -994,10 +931,9 @@ module internal HttpClientGenerator =
|
||||
None
|
||||
)
|
||||
|
||||
let pattern = SynLongIdent.CreateString "make"
|
||||
let pattern = SynLongIdent.createS "make"
|
||||
|
||||
let returnInfo =
|
||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name)
|
||||
let returnInfo = SynType.createLongIdent interfaceType.Name
|
||||
|
||||
let nameWithoutLeadingI =
|
||||
List.last interfaceType.Name
|
||||
@@ -1011,64 +947,49 @@ module internal HttpClientGenerator =
|
||||
let createFunc =
|
||||
if spec.ExtensionMethods then
|
||||
let binding =
|
||||
SynBinding.basic
|
||||
(SynLongIdent.CreateString "make")
|
||||
(headerArgs @ [ clientCreationArg ])
|
||||
interfaceImpl
|
||||
SynBinding.basic (SynLongIdent.createS "make") (headerArgs @ [ clientCreationArg ]) interfaceImpl
|
||||
|> SynBinding.withXmlDoc xmlDoc
|
||||
|> SynBinding.makeStaticMember
|
||||
|> 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 =
|
||||
SynTypeDefn.SynTypeDefn (
|
||||
SynComponentInfo.Create (
|
||||
[ Ident.Create nameWithoutLeadingI ],
|
||||
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
|
||||
}
|
||||
)
|
||||
SynTypeDefnRepr.augmentation ()
|
||||
|> SynTypeDefn.create componentInfo
|
||||
|> SynTypeDefn.withMemberDefns [ binding ]
|
||||
|
||||
SynModuleDecl.Types ([ containingType ], range0)
|
||||
|
||||
else
|
||||
SynBinding.basic (SynLongIdent.CreateString "make") (headerArgs @ [ clientCreationArg ]) interfaceImpl
|
||||
SynBinding.basic (SynLongIdent.createS "make") (headerArgs @ [ clientCreationArg ]) interfaceImpl
|
||||
|> SynBinding.withXmlDoc xmlDoc
|
||||
|> SynBinding.withReturnAnnotation returnInfo
|
||||
|> List.singleton
|
||||
|> SynModuleDecl.CreateLet
|
||||
|
||||
let moduleName : LongIdent =
|
||||
let moduleName =
|
||||
if spec.ExtensionMethods then
|
||||
[ Ident.Create (nameWithoutLeadingI + "HttpClientExtension") ]
|
||||
Ident.create (nameWithoutLeadingI + "HttpClientExtension")
|
||||
else
|
||||
[ Ident.Create nameWithoutLeadingI ]
|
||||
Ident.create nameWithoutLeadingI
|
||||
|
||||
let attribs =
|
||||
if spec.ExtensionMethods then
|
||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
||||
[ SynAttribute.autoOpen ]
|
||||
else
|
||||
[
|
||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
||||
SynAttribute.compilationRepresentation
|
||||
SynAttribute.RequireQualifiedAccess ()
|
||||
]
|
||||
|
||||
let modInfo =
|
||||
SynComponentInfo.Create (
|
||||
moduleName,
|
||||
attributes = attribs,
|
||||
xmldoc = docString,
|
||||
access = interfaceType.Accessibility
|
||||
)
|
||||
SynComponentInfo.create moduleName
|
||||
|> SynComponentInfo.withDocString docString
|
||||
|> SynComponentInfo.addAttributes attribs
|
||||
|> SynComponentInfo.setAccessibility interfaceType.Accessibility
|
||||
|
||||
SynModuleOrNamespace.CreateNamespace (
|
||||
ns,
|
||||
|
@@ -48,9 +48,9 @@ module internal InterfaceMockGenerator =
|
||||
|
||||
let failwithFun =
|
||||
SynExpr.createLongIdent [ "System" ; "NotImplementedException" ]
|
||||
|> SynExpr.applyTo (SynExpr.CreateConstString "Unimplemented mock function")
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst "Unimplemented mock function")
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "raise")
|
||||
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||
|> SynExpr.createLambda "_"
|
||||
|
||||
let constructorReturnType =
|
||||
@@ -60,38 +60,28 @@ module internal InterfaceMockGenerator =
|
||||
|
||||
let generics =
|
||||
generics.TyparDecls
|
||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|
||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||
|
||||
SynType.App (
|
||||
SynType.CreateLongIdent name,
|
||||
Some range0,
|
||||
generics,
|
||||
List.replicate (generics.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
SynType.app name generics
|
||||
|
||||
let constructorFields =
|
||||
let extras =
|
||||
if inherits.Contains KnownInheritance.IDisposable then
|
||||
let unitFun = SynExpr.createLambda "_" SynExpr.CreateUnit
|
||||
|
||||
[
|
||||
(SynLongIdent.CreateFromLongIdent [ Ident.Create "Dispose" ], true), Some unitFun
|
||||
]
|
||||
[ (SynLongIdent.createS "Dispose", true), Some unitFun ]
|
||||
else
|
||||
[]
|
||||
|
||||
let nonExtras =
|
||||
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
|
||||
|
||||
let constructor =
|
||||
SynBinding.basic
|
||||
(SynLongIdent.CreateString "Empty")
|
||||
(SynLongIdent.createS "Empty")
|
||||
(if interfaceType.Generics.IsNone then
|
||||
[]
|
||||
else
|
||||
@@ -184,7 +174,7 @@ module internal InterfaceMockGenerator =
|
||||
|
||||
let headPat =
|
||||
SynPat.LongIdent (
|
||||
SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; memberInfo.Identifier ],
|
||||
SynLongIdent.create [ Ident.Create "this" ; memberInfo.Identifier ],
|
||||
None,
|
||||
None,
|
||||
SynArgPats.Pats headArgs,
|
||||
@@ -199,8 +189,8 @@ module internal InterfaceMockGenerator =
|
||||
args.Args
|
||||
|> List.mapi (fun j arg ->
|
||||
match arg.Type with
|
||||
| UnitType -> SynExpr.CreateConst SynConst.Unit
|
||||
| _ -> SynExpr.CreateIdentString $"arg_%i{i}_%i{j}"
|
||||
| UnitType -> SynExpr.CreateConst ()
|
||||
| _ -> SynExpr.createIdent $"arg_%i{i}_%i{j}"
|
||||
)
|
||||
|> SynExpr.CreateParenedTuple
|
||||
)
|
||||
@@ -240,8 +230,7 @@ module internal InterfaceMockGenerator =
|
||||
)
|
||||
|
||||
let interfaceName =
|
||||
let baseName =
|
||||
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name)
|
||||
let baseName = SynType.createLongIdent interfaceType.Name
|
||||
|
||||
match interfaceType.Generics with
|
||||
| None -> baseName
|
||||
@@ -251,17 +240,9 @@ module internal InterfaceMockGenerator =
|
||||
| SynTyparDecls.PostfixList (decls, _, _) -> decls
|
||||
| SynTyparDecls.PrefixList (decls, _) -> decls
|
||||
| SynTyparDecls.SinglePrefix (decl, _) -> [ decl ]
|
||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|
||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||
|
||||
SynType.App (
|
||||
baseName,
|
||||
Some range0,
|
||||
generics,
|
||||
List.replicate (generics.Length - 1) range0,
|
||||
Some range0,
|
||||
false,
|
||||
range0
|
||||
)
|
||||
SynType.app' baseName generics
|
||||
|
||||
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
||||
|
||||
@@ -281,7 +262,7 @@ module internal InterfaceMockGenerator =
|
||||
| KnownInheritance.IDisposable ->
|
||||
let binding =
|
||||
SynBinding.basic
|
||||
(SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; Ident.Create "Dispose" ])
|
||||
(SynLongIdent.createS' [ "this" ; "Dispose" ])
|
||||
[ SynPat.CreateConst SynConst.Unit ]
|
||||
(SynExpr.CreateApp (SynExpr.createLongIdent [ "this" ; "Dispose" ], SynExpr.CreateUnit))
|
||||
|> SynBinding.withReturnAnnotation (SynType.Unit ())
|
||||
@@ -290,7 +271,7 @@ module internal InterfaceMockGenerator =
|
||||
let mem = SynMemberDefn.Member (binding, range0)
|
||||
|
||||
SynMemberDefn.Interface (
|
||||
SynType.CreateLongIdent (SynLongIdent.Create [ "System" ; "IDisposable" ]),
|
||||
SynType.CreateLongIdent (SynLongIdent.createS' [ "System" ; "IDisposable" ]),
|
||||
Some range0,
|
||||
Some [ mem ],
|
||||
range0
|
||||
@@ -314,7 +295,7 @@ module internal InterfaceMockGenerator =
|
||||
|
||||
let private buildType (x : ParameterInfo) : SynType =
|
||||
if x.IsOptional then
|
||||
SynType.App (SynType.CreateLongIdent "option", Some range0, [ x.Type ], [], Some range0, false, range0)
|
||||
SynType.app "option" [ x.Type ]
|
||||
else
|
||||
x.Type
|
||||
|
||||
|
@@ -30,30 +30,23 @@ module internal JsonParseGenerator =
|
||||
/// (match {indexed} with | null -> raise (System.Collections.Generic.KeyNotFoundException ()) | v -> v)
|
||||
let assertNotNull (propertyName : SynExpr) (indexed : SynExpr) =
|
||||
let raiseExpr =
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateIdentString "sprintf",
|
||||
SynExpr.CreateConstString "Required key '%s' not found on JSON object"
|
||||
),
|
||||
SynExpr.CreateParen propertyName
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createIdent "sprintf")
|
||||
(SynExpr.CreateConst "Required key '%s' not found on JSON object")
|
||||
|> SynExpr.applyTo (SynExpr.paren propertyName)
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (
|
||||
SynExpr.CreateLongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ]
|
||||
)
|
||||
SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ]
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "raise")
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||
|
||||
SynExpr.CreateMatch (
|
||||
indexed,
|
||||
[
|
||||
SynMatchClause.Create (SynPat.CreateNull, None, raiseExpr)
|
||||
SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, SynExpr.CreateIdentString "v")
|
||||
]
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
[
|
||||
SynMatchClause.create SynPat.CreateNull raiseExpr
|
||||
SynMatchClause.create (SynPat.named "v") (SynExpr.createIdent "v")
|
||||
]
|
||||
|> SynExpr.createMatch indexed
|
||||
|> SynExpr.paren
|
||||
|
||||
/// {node}.AsValue().GetValue<{typeName}> ()
|
||||
/// If `propertyName` is Some, uses `assertNotNull {node}` instead of `{node}`.
|
||||
@@ -81,10 +74,8 @@ module internal JsonParseGenerator =
|
||||
|
||||
/// {type}.jsonParse {node}
|
||||
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.
|
||||
/// body is the body of a lambda which takes a parameter `elt`.
|
||||
@@ -103,51 +94,40 @@ module internal JsonParseGenerator =
|
||||
| Some propertyName -> assertNotNull propertyName node
|
||||
|> SynExpr.callMethod "AsArray"
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
||||
SynExpr.createLambda "elt" body
|
||||
)
|
||||
SynExpr.applyFunction (SynExpr.createLongIdent [ "Seq" ; "map" ]) (SynExpr.createLambda "elt" body)
|
||||
)
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ collectionType ; "ofSeq" ]))
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ collectionType ; "ofSeq" ])
|
||||
|
||||
/// match {node} with | null -> None | v -> {body} |> Some
|
||||
/// Use the variable `v` to get access to the `Some`.
|
||||
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.CreateNamed (Ident.Create "v"), None, body)
|
||||
]
|
||||
)
|
||||
[
|
||||
SynMatchClause.create SynPat.CreateNull (SynExpr.createIdent "None")
|
||||
SynMatchClause.create (SynPat.named "v") body
|
||||
]
|
||||
|> SynExpr.createMatch node
|
||||
|
||||
/// Given e.g. "float", returns "System.Double.Parse"
|
||||
let parseFunction (typeName : string) : LongIdent =
|
||||
let qualified =
|
||||
match AstHelper.qualifyPrimitiveType typeName with
|
||||
match Primitives.qualifyType typeName with
|
||||
| Some x -> x
|
||||
| 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))
|
||||
/// 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 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.createLet
|
||||
[
|
||||
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.CreateTuple [ SynExpr.createIdent "key" ; SynExpr.createIdent "value" ]
|
||||
|> SynExpr.createLet [ SynBinding.Let (pattern = SynPat.named "value", expr = value valueArg) ]
|
||||
|> SynExpr.createLet [ SynBinding.Let (pattern = SynPat.named "key", expr = key keyArg) ]
|
||||
|> SynExpr.createLambda "kvp"
|
||||
|
||||
/// A conforming JSON object has only strings as keys. But it would be reasonable to allow the user
|
||||
@@ -157,7 +137,7 @@ module internal JsonParseGenerator =
|
||||
| String -> key
|
||||
| Uri ->
|
||||
key
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ]))
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Uri" ])
|
||||
| _ ->
|
||||
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."
|
||||
@@ -197,15 +177,8 @@ module internal JsonParseGenerator =
|
||||
| None -> basic
|
||||
| Some option ->
|
||||
let cond =
|
||||
SynExpr.DotGet (
|
||||
SynExpr.CreateIdentString "exc",
|
||||
range0,
|
||||
SynLongIdent.CreateString "Message",
|
||||
range0
|
||||
)
|
||||
|> SynExpr.callMethodArg
|
||||
"Contains"
|
||||
(SynExpr.CreateConst (SynConst.CreateString "cannot be converted to"))
|
||||
SynExpr.DotGet (SynExpr.createIdent "exc", range0, SynLongIdent.createS "Message", range0)
|
||||
|> SynExpr.callMethodArg "Contains" (SynExpr.CreateConst "cannot be converted to")
|
||||
|
||||
let handler =
|
||||
asValueGetValue propertyName "string" node
|
||||
@@ -213,91 +186,82 @@ module internal JsonParseGenerator =
|
||||
|> SynExpr.ifThenElse
|
||||
(SynExpr.equals
|
||||
option
|
||||
(SynExpr.CreateLongIdent (
|
||||
SynLongIdent.Create
|
||||
[
|
||||
"System"
|
||||
"Text"
|
||||
"Json"
|
||||
"Serialization"
|
||||
"JsonNumberHandling"
|
||||
"AllowReadingFromString"
|
||||
]
|
||||
)))
|
||||
(SynExpr.createLongIdent
|
||||
[
|
||||
"System"
|
||||
"Text"
|
||||
"Json"
|
||||
"Serialization"
|
||||
"JsonNumberHandling"
|
||||
"AllowReadingFromString"
|
||||
]))
|
||||
SynExpr.reraise
|
||||
|> SynExpr.ifThenElse cond SynExpr.reraise
|
||||
|
||||
basic
|
||||
|> SynExpr.pipeThroughTryWith
|
||||
(SynPat.IsInst (
|
||||
SynType.LongIdent (SynLongIdent.Create [ "System" ; "InvalidOperationException" ]),
|
||||
SynType.LongIdent (SynLongIdent.createS' [ "System" ; "InvalidOperationException" ]),
|
||||
range0
|
||||
))
|
||||
handler
|
||||
| PrimitiveType typeName -> asValueGetValueIdent propertyName typeName node
|
||||
| OptionType ty ->
|
||||
parseNode None options ty (SynExpr.CreateIdentString "v")
|
||||
parseNode None options ty (SynExpr.createIdent "v")
|
||||
|> createParseLineOption node
|
||||
| ListType ty ->
|
||||
parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"))
|
||||
parseNode None options ty (SynExpr.createIdent "elt")
|
||||
|> asArrayMapped propertyName "List" node
|
||||
| ArrayType ty ->
|
||||
parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"))
|
||||
parseNode None options ty (SynExpr.createIdent "elt")
|
||||
|> asArrayMapped propertyName "Array" node
|
||||
| IDictionaryType (keyType, valueType) ->
|
||||
node
|
||||
|> asObject propertyName
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||
)
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "dict" ]))
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.createIdent "dict")
|
||||
| DictionaryType (keyType, valueType) ->
|
||||
node
|
||||
|> asObject propertyName
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||
)
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
||||
SynExpr.CreateLongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ]
|
||||
)
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||
(SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ])
|
||||
)
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "Dictionary" ])
|
||||
SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "Dictionary" ]
|
||||
)
|
||||
| IReadOnlyDictionaryType (keyType, valueType) ->
|
||||
node
|
||||
|> asObject propertyName
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||
)
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "readOnlyDict" ]))
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.createIdent "readOnlyDict")
|
||||
| MapType (keyType, valueType) ->
|
||||
node
|
||||
|> asObject propertyName
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||
)
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Map" ; "ofSeq" ]))
|
||||
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "Map" ; "ofSeq" ])
|
||||
| BigInt ->
|
||||
node
|
||||
|> SynExpr.callMethod "ToJsonString"
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "Numerics" ; "BigInteger" ; "Parse" ])
|
||||
| _ ->
|
||||
// Let's just hope that we've also got our own type annotation!
|
||||
@@ -314,7 +278,7 @@ module internal JsonParseGenerator =
|
||||
/// 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).
|
||||
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
|
||||
|
||||
let isJsonNumberHandling (literal : LongIdent) : bool =
|
||||
@@ -331,45 +295,36 @@ module internal JsonParseGenerator =
|
||||
/// That is, we give you access to a `JsonNode` called `node`,
|
||||
/// and you must return a `typeName`.
|
||||
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 functionName = Ident.Create "jsonParse"
|
||||
let inputArg = "node"
|
||||
let functionName = Ident.create "jsonParse"
|
||||
|
||||
let arg =
|
||||
SynPat.CreateNamed inputArg
|
||||
|> SynPat.annotateType (
|
||||
SynType.LongIdent (SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||
)
|
||||
SynPat.named inputArg
|
||||
|> SynPat.annotateType (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||
|
||||
if spec.ExtensionMethods then
|
||||
let binding =
|
||||
SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ arg ] functionBody
|
||||
|> SynBinding.makeStaticMember
|
||||
SynBinding.basic (SynLongIdent.createI functionName) [ arg ] functionBody
|
||||
|> SynBinding.withXmlDoc xmlDoc
|
||||
|> 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 =
|
||||
SynTypeDefn.SynTypeDefn (
|
||||
SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"),
|
||||
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0),
|
||||
[ mem ],
|
||||
None,
|
||||
range0,
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
EqualsRange = None
|
||||
WithKeyword = None
|
||||
}
|
||||
)
|
||||
SynTypeDefnRepr.augmentation ()
|
||||
|> SynTypeDefn.create componentInfo
|
||||
|> SynTypeDefn.withMemberDefns [ binding ]
|
||||
|
||||
SynModuleDecl.Types ([ containingType ], range0)
|
||||
else
|
||||
SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ arg ] functionBody
|
||||
SynBinding.basic (SynLongIdent.createI functionName) [ arg ] functionBody
|
||||
|> SynBinding.withXmlDoc xmlDoc
|
||||
|> SynBinding.withReturnAnnotation returnInfo
|
||||
|> List.singleton
|
||||
@@ -425,18 +380,17 @@ module internal JsonParseGenerator =
|
||||
if fieldData.Ident.idText.Length > 1 then
|
||||
sb.Append (fieldData.Ident.idText.Substring 1) |> ignore<StringBuilder>
|
||||
|
||||
sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst
|
||||
sb.ToString () |> SynExpr.CreateConst
|
||||
| Some name -> name.ArgExpr
|
||||
|
||||
createParseRhs options propertyName fieldData.Type
|
||||
|> SynBinding.basic (SynLongIdent.CreateString $"arg_%i{i}") []
|
||||
|> SynBinding.basic (SynLongIdent.createS $"arg_%i{i}") []
|
||||
)
|
||||
|
||||
let finalConstruction =
|
||||
fields
|
||||
|> List.mapi (fun i fieldData ->
|
||||
(SynLongIdent.CreateFromLongIdent [ fieldData.Ident ], true),
|
||||
Some (SynExpr.CreateLongIdent (SynLongIdent.CreateString $"arg_%i{i}"))
|
||||
(SynLongIdent.createI fieldData.Ident, true), Some (SynExpr.createIdent $"arg_%i{i}")
|
||||
)
|
||||
|> AstHelper.instantiateRecord
|
||||
|
||||
@@ -462,9 +416,9 @@ module internal JsonParseGenerator =
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ case.Ident ]))
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.index (SynExpr.CreateConstString "data") (SynExpr.CreateIdentString "node")
|
||||
|> assertNotNull (SynExpr.CreateConstString "data")
|
||||
|> SynBinding.basic (SynLongIdent.CreateString "node") []
|
||||
SynExpr.index (SynExpr.CreateConst "data") (SynExpr.createIdent "node")
|
||||
|> assertNotNull (SynExpr.CreateConst "data")
|
||||
|> SynBinding.basic (SynLongIdent.createS "node") []
|
||||
]
|
||||
|
||||
match propertyName with
|
||||
@@ -481,30 +435,19 @@ module internal JsonParseGenerator =
|
||||
}
|
||||
)
|
||||
| _ ->
|
||||
SynMatchClause.SynMatchClause (
|
||||
SynPat.CreateNamed (Ident.Create "x"),
|
||||
Some (SynExpr.equals (SynExpr.CreateIdentString "x") propertyName),
|
||||
body,
|
||||
range0,
|
||||
DebugPointAtTarget.Yes,
|
||||
{
|
||||
ArrowRange = Some range0
|
||||
BarRange = Some range0
|
||||
}
|
||||
)
|
||||
SynMatchClause.create (SynPat.named "x") body
|
||||
|> SynMatchClause.withWhere (SynExpr.equals (SynExpr.createIdent "x") propertyName)
|
||||
)
|
||||
|> fun l ->
|
||||
l
|
||||
@ [
|
||||
let fail =
|
||||
SynExpr.plus
|
||||
(SynExpr.CreateConstString "Unrecognised 'type' field value: ")
|
||||
(SynExpr.CreateIdentString "v")
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.applyFunction (SynExpr.CreateIdentString "failwith")
|
||||
SynExpr.plus (SynExpr.CreateConst "Unrecognised 'type' field value: ") (SynExpr.createIdent "v")
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.applyFunction (SynExpr.createIdent "failwith")
|
||||
|
||||
SynMatchClause.SynMatchClause (
|
||||
SynPat.CreateNamed (Ident.Create "v"),
|
||||
SynPat.named "v",
|
||||
None,
|
||||
fail,
|
||||
range0,
|
||||
@@ -515,34 +458,21 @@ module internal JsonParseGenerator =
|
||||
}
|
||||
)
|
||||
]
|
||||
|> SynExpr.createMatch (SynExpr.CreateIdentString "ty")
|
||||
|> SynExpr.createMatch (SynExpr.createIdent "ty")
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
let property = SynExpr.CreateConstString "type"
|
||||
let property = SynExpr.CreateConst "type"
|
||||
|
||||
SynExpr.CreateIdentString "node"
|
||||
SynExpr.createIdent "node"
|
||||
|> SynExpr.index property
|
||||
|> assertNotNull property
|
||||
|> SynExpr.pipeThroughFunction (
|
||||
SynExpr.createLambda
|
||||
"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 (SynLongIdent.createS "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 (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||
@@ -553,11 +483,11 @@ module internal JsonParseGenerator =
|
||||
|
||||
let attributes =
|
||||
if spec.ExtensionMethods then
|
||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
||||
[ SynAttribute.autoOpen ]
|
||||
else
|
||||
[
|
||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
||||
SynAttribute.RequireQualifiedAccess ()
|
||||
SynAttribute.compilationRepresentation
|
||||
]
|
||||
|
||||
let xmlDoc =
|
||||
@@ -581,14 +511,16 @@ module internal JsonParseGenerator =
|
||||
List.last ident
|
||||
|> fun i -> i.idText
|
||||
|> fun s -> s + "JsonParseExtension"
|
||||
|> Ident.Create
|
||||
|> Ident.create
|
||||
|
||||
List.take (List.length ident - 1) ident @ [ expanded ]
|
||||
else
|
||||
ident
|
||||
|
||||
let info =
|
||||
SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc)
|
||||
SynComponentInfo.createLong moduleName
|
||||
|> SynComponentInfo.withDocString xmlDoc
|
||||
|> SynComponentInfo.addAttributes attributes
|
||||
|
||||
let decl =
|
||||
match synTypeDefnRepr with
|
||||
|
@@ -42,35 +42,27 @@ module internal JsonSerializeGenerator =
|
||||
// fun field -> match field with | None -> JsonValue.Create null | Some v -> {serializeNode ty} field
|
||||
[
|
||||
SynMatchClause.Create (
|
||||
SynPat.CreateLongIdent (SynLongIdent.CreateString "None", []),
|
||||
SynPat.CreateLongIdent (SynLongIdent.createS "None", []),
|
||||
None,
|
||||
// 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
|
||||
// be efficient here and whip up the null directly.
|
||||
SynExpr.CreateNull
|
||||
|> SynExpr.upcast' (
|
||||
SynType.CreateLongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||
)
|
||||
SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
SynMatchClause.Create (
|
||||
SynPat.CreateLongIdent (
|
||||
SynLongIdent.CreateString "Some",
|
||||
[ SynPat.CreateNamed (Ident.Create "field") ]
|
||||
),
|
||||
SynPat.CreateLongIdent (SynLongIdent.createS "Some", [ SynPat.named "field" ]),
|
||||
None,
|
||||
SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "field")
|
||||
|> SynExpr.CreateParen
|
||||
|> SynExpr.upcast' (
|
||||
SynType.CreateLongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||
)
|
||||
)
|
||||
SynExpr.applyFunction (serializeNode ty) (SynExpr.createIdent "field")
|
||||
|> SynExpr.paren
|
||||
|> SynExpr.upcast' (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||
)
|
||||
]
|
||||
|> SynExpr.createMatch (SynExpr.CreateIdentString "field")
|
||||
|> SynExpr.createMatch (SynExpr.createIdent "field")
|
||||
|> SynExpr.createLambda "field"
|
||||
| ArrayType ty
|
||||
| ListType ty ->
|
||||
@@ -84,22 +76,21 @@ module internal JsonSerializeGenerator =
|
||||
DebugPointAtInOrTo.Yes range0,
|
||||
SeqExprOnly.SeqExprOnly false,
|
||||
true,
|
||||
SynPat.CreateNamed (Ident.Create "mem"),
|
||||
SynExpr.CreateIdent (Ident.Create "field"),
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "arr" ; "Add" ]),
|
||||
SynExpr.CreateParen (SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "mem"))
|
||||
),
|
||||
SynPat.named "mem",
|
||||
SynExpr.createIdent "field",
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.CreateLongIdent (SynLongIdent.createS' [ "arr" ; "Add" ]))
|
||||
(SynExpr.CreateParen (SynExpr.CreateApp (serializeNode ty, SynExpr.createIdent "mem"))),
|
||||
range0
|
||||
)
|
||||
SynExpr.CreateIdentString "arr"
|
||||
SynExpr.createIdent "arr"
|
||||
]
|
||||
|> SynExpr.CreateSequential
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonArray" ]
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
|> SynBinding.basic (SynLongIdent.CreateString "arr") []
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
|> SynBinding.basic (SynLongIdent.createS "arr") []
|
||||
]
|
||||
|> SynExpr.createLambda "field"
|
||||
| IDictionaryType (_keyType, valueType)
|
||||
@@ -119,7 +110,7 @@ module internal JsonSerializeGenerator =
|
||||
true,
|
||||
SynPat.CreateParen (
|
||||
SynPat.CreateLongIdent (
|
||||
SynLongIdent.CreateString "KeyValue",
|
||||
SynLongIdent.createS "KeyValue",
|
||||
[
|
||||
SynPat.CreateParen (
|
||||
SynPat.Tuple (
|
||||
@@ -142,21 +133,21 @@ module internal JsonSerializeGenerator =
|
||||
[
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "key" ; "ToString" ],
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
SynExpr.CreateConst ()
|
||||
)
|
||||
SynExpr.CreateApp (serializeNode valueType, SynExpr.CreateIdentString "value")
|
||||
SynExpr.CreateApp (serializeNode valueType, SynExpr.createIdent "value")
|
||||
]
|
||||
),
|
||||
range0
|
||||
)
|
||||
SynExpr.CreateIdentString "ret"
|
||||
SynExpr.createIdent "ret"
|
||||
]
|
||||
|> SynExpr.CreateSequential
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
|> SynBinding.basic (SynLongIdent.CreateString "ret") []
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
|> SynBinding.basic (SynLongIdent.createS "ret") []
|
||||
]
|
||||
|> SynExpr.createLambda "field"
|
||||
| _ ->
|
||||
@@ -173,7 +164,9 @@ module internal JsonSerializeGenerator =
|
||||
let createSerializeRhsRecord (propertyName : SynExpr) (fieldId : Ident) (fieldType : SynType) : SynExpr =
|
||||
[
|
||||
propertyName
|
||||
SynExpr.CreateApp (serializeNode fieldType, SynExpr.createLongIdent' [ Ident.Create "input" ; fieldId ])
|
||||
SynExpr.applyFunction
|
||||
(serializeNode fieldType)
|
||||
(SynExpr.createLongIdent' [ Ident.create "input" ; fieldId ])
|
||||
]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||
@@ -191,7 +184,7 @@ module internal JsonSerializeGenerator =
|
||||
if fieldId.idText.Length > 1 then
|
||||
sb.Append fieldId.idText.[1..] |> ignore
|
||||
|
||||
sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst
|
||||
sb.ToString () |> SynExpr.CreateConst
|
||||
| Some name -> name.ArgExpr
|
||||
|
||||
/// `populateNode` will be inserted before we return the `node` variable.
|
||||
@@ -207,67 +200,60 @@ module internal JsonSerializeGenerator =
|
||||
(populateNode : SynExpr)
|
||||
: SynModuleDecl
|
||||
=
|
||||
let xmlDoc = PreXmlDoc.Create " Serialize to a JSON node"
|
||||
let xmlDoc = PreXmlDoc.create "Serialize to a JSON node"
|
||||
|
||||
let returnInfo =
|
||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||
SynLongIdent.createS' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||
|> SynType.LongIdent
|
||||
|
||||
let functionName = Ident.Create "toJsonNode"
|
||||
let functionName = Ident.create "toJsonNode"
|
||||
|
||||
let assignments =
|
||||
[
|
||||
populateNode
|
||||
SynExpr.Upcast (SynExpr.CreateIdentString "node", SynType.Anon range0, range0)
|
||||
SynExpr.Upcast (SynExpr.createIdent "node", SynType.Anon range0, range0)
|
||||
]
|
||||
|> SynExpr.CreateSequential
|
||||
|> SynExpr.createLet
|
||||
[
|
||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
|> SynBinding.basic (SynLongIdent.CreateString "node") []
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
|> SynBinding.basic (SynLongIdent.createS "node") []
|
||||
]
|
||||
|
||||
let pattern =
|
||||
SynPat.CreateNamed inputArgName
|
||||
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName))
|
||||
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create typeName))
|
||||
|
||||
if spec.ExtensionMethods then
|
||||
let binding =
|
||||
let componentInfo =
|
||||
SynComponentInfo.createLong typeName
|
||||
|> SynComponentInfo.withDocString (PreXmlDoc.Create " Extension methods for JSON parsing")
|
||||
|
||||
let memberDef =
|
||||
assignments
|
||||
|> SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ pattern ]
|
||||
|> SynBinding.basic (SynLongIdent.createI functionName) [ pattern ]
|
||||
|> SynBinding.withXmlDoc xmlDoc
|
||||
|> SynBinding.withReturnAnnotation returnInfo
|
||||
|> SynBinding.makeStaticMember
|
||||
|
||||
let mem = SynMemberDefn.Member (binding, range0)
|
||||
|> SynMemberDefn.staticMember
|
||||
|
||||
let containingType =
|
||||
SynTypeDefn.SynTypeDefn (
|
||||
SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"),
|
||||
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0),
|
||||
[ mem ],
|
||||
None,
|
||||
range0,
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
EqualsRange = None
|
||||
WithKeyword = None
|
||||
}
|
||||
)
|
||||
SynTypeDefnRepr.augmentation ()
|
||||
|> SynTypeDefn.create componentInfo
|
||||
|> SynTypeDefn.withMemberDefns [ memberDef ]
|
||||
|
||||
SynModuleDecl.Types ([ containingType ], range0)
|
||||
else
|
||||
let binding =
|
||||
assignments
|
||||
|> SynBinding.basic (SynLongIdent.CreateFromLongIdent [ functionName ]) [ pattern ]
|
||||
|> SynBinding.basic (SynLongIdent.createI functionName) [ pattern ]
|
||||
|> SynBinding.withReturnAnnotation returnInfo
|
||||
|> SynBinding.withXmlDoc xmlDoc
|
||||
|
||||
SynModuleDecl.CreateLet [ binding ]
|
||||
|
||||
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
|
||||
|
||||
fields
|
||||
@@ -280,20 +266,20 @@ module internal JsonSerializeGenerator =
|
||||
|> scaffolding spec typeName inputArg
|
||||
|
||||
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
|
||||
|
||||
fields
|
||||
|> List.map (fun unionCase ->
|
||||
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 pattern =
|
||||
SynPat.LongIdent (
|
||||
SynLongIdent.CreateFromLongIdent (typeName @ [ unionCase.Ident ]),
|
||||
SynLongIdent.create (typeName @ [ unionCase.Ident ]),
|
||||
None,
|
||||
None,
|
||||
argPats,
|
||||
@@ -303,25 +289,21 @@ module internal JsonSerializeGenerator =
|
||||
|
||||
let typeLine =
|
||||
[
|
||||
SynExpr.CreateConstString "type"
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ],
|
||||
SynExpr.CreateConst "type"
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ])
|
||||
propertyName
|
||||
)
|
||||
]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||
|
||||
let dataNode =
|
||||
SynBinding.Let (
|
||||
pattern = SynPat.CreateNamed (Ident.Create "dataNode"),
|
||||
pattern = SynPat.named "dataNode",
|
||||
expr =
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||
),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
)
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ])
|
||||
(SynExpr.CreateConst ())
|
||||
)
|
||||
|
||||
let dataBindings =
|
||||
@@ -331,7 +313,7 @@ module internal JsonSerializeGenerator =
|
||||
let propertyName = getPropertyName (Option.get fieldData.Ident) fieldData.Attrs
|
||||
|
||||
let node =
|
||||
SynExpr.CreateApp (serializeNode fieldData.Type, SynExpr.CreateIdent caseName)
|
||||
SynExpr.applyFunction (serializeNode fieldData.Type) (SynExpr.createIdent' caseName)
|
||||
|
||||
[ propertyName ; node ]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
@@ -339,7 +321,7 @@ module internal JsonSerializeGenerator =
|
||||
)
|
||||
|
||||
let assignToNode =
|
||||
[ SynExpr.CreateConstString "data" ; SynExpr.CreateIdentString "dataNode" ]
|
||||
[ SynExpr.CreateConst "data" ; SynExpr.createIdent "dataNode" ]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||
|
||||
@@ -355,9 +337,9 @@ module internal JsonSerializeGenerator =
|
||||
]
|
||||
|> SynExpr.CreateSequential
|
||||
|
||||
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
|
||||
|
||||
let createModule
|
||||
@@ -374,11 +356,11 @@ module internal JsonSerializeGenerator =
|
||||
|
||||
let attributes =
|
||||
if spec.ExtensionMethods then
|
||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
||||
[ SynAttribute.autoOpen ]
|
||||
else
|
||||
[
|
||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
||||
SynAttribute.RequireQualifiedAccess ()
|
||||
SynAttribute.compilationRepresentation
|
||||
]
|
||||
|
||||
let xmlDoc =
|
||||
@@ -390,8 +372,8 @@ module internal JsonSerializeGenerator =
|
||||
else
|
||||
"methods"
|
||||
|
||||
$" Module containing JSON serializing %s{description} for the %s{fullyQualified} type"
|
||||
|> PreXmlDoc.Create
|
||||
$"Module containing JSON serializing %s{description} for the %s{fullyQualified} type"
|
||||
|> PreXmlDoc.create
|
||||
|
||||
let moduleName =
|
||||
if spec.ExtensionMethods then
|
||||
@@ -402,14 +384,16 @@ module internal JsonSerializeGenerator =
|
||||
List.last ident
|
||||
|> fun i -> i.idText
|
||||
|> fun s -> s + "JsonSerializeExtension"
|
||||
|> Ident.Create
|
||||
|> Ident.create
|
||||
|
||||
List.take (List.length ident - 1) ident @ [ expanded ]
|
||||
else
|
||||
ident
|
||||
|
||||
let info =
|
||||
SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc)
|
||||
SynComponentInfo.createLong moduleName
|
||||
|> SynComponentInfo.addAttributes attributes
|
||||
|> SynComponentInfo.withDocString xmlDoc
|
||||
|
||||
let decls =
|
||||
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))))
|
@@ -47,7 +47,7 @@ module internal RemoveOptionsGenerator =
|
||||
(fields : SynField list)
|
||||
=
|
||||
let fields : SynField list = fields |> List.map removeOption
|
||||
let name = Ident.Create "Short"
|
||||
let name = Ident.create "Short"
|
||||
|
||||
let record =
|
||||
{
|
||||
@@ -64,20 +64,10 @@ module internal RemoveOptionsGenerator =
|
||||
SynModuleDecl.Types ([ typeDecl ], range0)
|
||||
|
||||
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 =
|
||||
SynBindingReturnInfo.Create (SynType.LongIdent (SynLongIdent.CreateFromLongIdent withOptionsType))
|
||||
|
||||
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 inputArg = Ident.create "input"
|
||||
let functionName = Ident.create "shorten"
|
||||
|
||||
let body =
|
||||
fields
|
||||
@@ -93,8 +83,8 @@ module internal RemoveOptionsGenerator =
|
||||
let body =
|
||||
match fieldData.Type with
|
||||
| OptionType _ ->
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateAppInfix (
|
||||
SynExpr.applyFunction
|
||||
(SynExpr.CreateAppInfix (
|
||||
SynExpr.LongIdent (
|
||||
false,
|
||||
SynLongIdent.SynLongIdent (
|
||||
@@ -106,50 +96,29 @@ module internal RemoveOptionsGenerator =
|
||||
range0
|
||||
),
|
||||
accessor
|
||||
),
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "Option.defaultWith"),
|
||||
SynExpr.CreateLongIdent (
|
||||
SynLongIdent.CreateFromLongIdent (
|
||||
withoutOptionsType
|
||||
@ [ Ident.Create (sprintf "Default%s" fieldData.Ident.idText) ]
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
))
|
||||
(SynExpr.applyFunction
|
||||
(SynExpr.createLongIdent [ "Option" ; "defaultWith" ])
|
||||
(SynExpr.createLongIdent' (
|
||||
withoutOptionsType
|
||||
@ [ Ident.create (sprintf "Default%s" fieldData.Ident.idText) ]
|
||||
)))
|
||||
| _ -> accessor
|
||||
|
||||
(SynLongIdent.CreateFromLongIdent [ fieldData.Ident ], true), Some body
|
||||
(SynLongIdent.createI fieldData.Ident, true), Some body
|
||||
)
|
||||
|> 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 =
|
||||
SynBinding.Let (
|
||||
isInline = false,
|
||||
isMutable = false,
|
||||
xmldoc = xmlDoc,
|
||||
returnInfo = returnInfo,
|
||||
expr = body,
|
||||
valData = inputVal,
|
||||
pattern = pattern
|
||||
)
|
||||
SynBinding.basic
|
||||
(SynLongIdent.createI functionName)
|
||||
[
|
||||
SynPat.named inputArg.idText
|
||||
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create withoutOptionsType))
|
||||
]
|
||||
body
|
||||
|> SynBinding.withXmlDoc xmlDoc
|
||||
|> SynBinding.withReturnAnnotation (SynType.LongIdent (SynLongIdent.create withOptionsType))
|
||||
|
||||
SynModuleDecl.CreateLet [ binding ]
|
||||
|
||||
@@ -167,24 +136,21 @@ module internal RemoveOptionsGenerator =
|
||||
let decls =
|
||||
[
|
||||
createType (Some doc) accessibility typeParams fields
|
||||
createMaker [ Ident.Create "Short" ] recordId fieldData
|
||||
]
|
||||
|
||||
let attributes =
|
||||
[
|
||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
||||
createMaker [ Ident.create "Short" ] recordId fieldData
|
||||
]
|
||||
|
||||
let xmlDoc =
|
||||
recordId
|
||||
|> Seq.map (fun i -> i.idText)
|
||||
|> String.concat "."
|
||||
|> sprintf " Module containing an option-truncated version of the %s type"
|
||||
|> PreXmlDoc.Create
|
||||
|> sprintf "Module containing an option-truncated version of the %s type"
|
||||
|> PreXmlDoc.create
|
||||
|
||||
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)
|
||||
|
||||
|
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.Text
|
||||
open Fantomas.FCS.Syntax
|
||||
open Myriad.Core
|
||||
open Fantomas.FCS.Text.Range
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal Ident =
|
||||
let inline create (s : string) = Ident (s, range0)
|
||||
|
||||
let lowerFirstLetter (x : Ident) : Ident =
|
||||
let result = StringBuilder x.idText.Length
|
||||
result.Append (Char.ToLowerInvariant x.idText.[0]) |> 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)
|
@@ -8,11 +8,11 @@ open Myriad.Core
|
||||
module internal SynAttribute =
|
||||
let internal compilationRepresentation : SynAttribute =
|
||||
{
|
||||
TypeName = SynLongIdent.CreateString "CompilationRepresentation"
|
||||
TypeName = SynLongIdent.createS "CompilationRepresentation"
|
||||
ArgExpr =
|
||||
SynExpr.CreateLongIdent (
|
||||
false,
|
||||
SynLongIdent.Create [ "CompilationRepresentationFlags" ; "ModuleSuffix" ],
|
||||
SynLongIdent.createS' [ "CompilationRepresentationFlags" ; "ModuleSuffix" ],
|
||||
None
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
@@ -23,7 +23,7 @@ module internal SynAttribute =
|
||||
|
||||
let internal autoOpen : SynAttribute =
|
||||
{
|
||||
TypeName = SynLongIdent.CreateString "AutoOpen"
|
||||
TypeName = SynLongIdent.createS "AutoOpen"
|
||||
ArgExpr = SynExpr.CreateConst SynConst.Unit
|
||||
Target = None
|
||||
AppliesToGetterAndSetter = false
|
||||
|
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.SyntaxTrivia
|
||||
open Myriad.Core
|
||||
open Myriad.Core.Ast
|
||||
open Fantomas.FCS.Text.Range
|
||||
|
||||
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
|
||||
[<AutoOpen>]
|
||||
module internal SynExprExtensions =
|
||||
type SynExpr with
|
||||
static member CreateConst (s : string) : 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>]
|
||||
module internal SynExpr =
|
||||
@@ -58,7 +62,7 @@ module internal SynExpr =
|
||||
/// try {body} with | {exc} as exc -> {handler}
|
||||
let pipeThroughTryWith (exc : SynPat) (handler : SynExpr) (body : SynExpr) : SynExpr =
|
||||
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 (
|
||||
body,
|
||||
@@ -119,24 +123,24 @@ module internal SynExpr =
|
||||
|
||||
/// {obj}.{meth}()
|
||||
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 =
|
||||
SynExpr.TypeApp (
|
||||
SynExpr.DotGet (obj, range0, SynLongIdent.Create [ meth ], range0),
|
||||
SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0),
|
||||
range0,
|
||||
[ SynType.LongIdent (SynLongIdent.CreateFromLongIdent ty) ],
|
||||
[ SynType.LongIdent (SynLongIdent.create ty) ],
|
||||
[],
|
||||
Some range0,
|
||||
range0,
|
||||
range0
|
||||
)
|
||||
|> applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
|> applyTo (SynExpr.CreateConst ())
|
||||
|
||||
/// {obj}.{meth}<ty>()
|
||||
let callGenericMethod' (meth : string) (ty : string) (obj : SynExpr) : SynExpr =
|
||||
SynExpr.TypeApp (
|
||||
SynExpr.DotGet (obj, range0, SynLongIdent.Create [ meth ], range0),
|
||||
SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0),
|
||||
range0,
|
||||
[ SynType.CreateLongIdent ty ],
|
||||
[],
|
||||
@@ -144,14 +148,14 @@ module internal SynExpr =
|
||||
range0,
|
||||
range0
|
||||
)
|
||||
|> applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
|> applyTo (SynExpr.CreateConst ())
|
||||
|
||||
let index (property : SynExpr) (obj : SynExpr) : SynExpr =
|
||||
SynExpr.DotIndexedGet (obj, property, range0, range0)
|
||||
|
||||
/// (fun {varName} -> {body})
|
||||
let createLambda (varName : string) (body : SynExpr) : SynExpr =
|
||||
let parsedDataPat = [ SynPat.CreateNamed (Ident.Create varName) ]
|
||||
let parsedDataPat = [ SynPat.named varName ]
|
||||
|
||||
SynExpr.Lambda (
|
||||
false,
|
||||
@@ -166,38 +170,66 @@ module internal SynExpr =
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
|
||||
let reraise : SynExpr =
|
||||
SynExpr.CreateIdent (Ident.Create "reraise")
|
||||
|> applyTo (SynExpr.CreateConst SynConst.Unit)
|
||||
let createThunk (body : SynExpr) : SynExpr =
|
||||
let parsedDataPat = [ SynPat.Const (SynConst.Unit, range0) ]
|
||||
|
||||
SynExpr.Lambda (
|
||||
false,
|
||||
false,
|
||||
SynSimplePats.Create [],
|
||||
body,
|
||||
Some (parsedDataPat, body),
|
||||
range0,
|
||||
{
|
||||
ArrowRange = Some range0
|
||||
}
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
|
||||
/// {body} |> fun a -> Async.StartAsTask (a, ?cancellationToken=ct)
|
||||
let startAsTask (ct : SynLongIdent) (body : SynExpr) =
|
||||
let lambda =
|
||||
[
|
||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "a")
|
||||
SynExpr.CreateLongIdent (SynLongIdent.createS "a")
|
||||
equals
|
||||
(SynExpr.LongIdent (true, SynLongIdent.CreateString "cancellationToken", None, range0))
|
||||
(SynExpr.LongIdent (true, SynLongIdent.createS "cancellationToken", None, range0))
|
||||
(SynExpr.CreateLongIdent ct)
|
||||
]
|
||||
|> SynExpr.CreateParenedTuple
|
||||
|> applyFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "StartAsTask" ]))
|
||||
|> applyFunction (SynExpr.CreateLongIdent (SynLongIdent.createS' [ "Async" ; "StartAsTask" ]))
|
||||
|> createLambda "a"
|
||||
|
||||
pipeThroughFunction lambda body
|
||||
|
||||
let createLongIdent (ident : string list) : SynExpr =
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create ident)
|
||||
let inline createIdent (s : string) : SynExpr = SynExpr.Ident (Ident (s, range0))
|
||||
|
||||
let createLongIdent' (ident : Ident list) : SynExpr =
|
||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent ident)
|
||||
let inline createIdent' (i : Ident) : SynExpr = SynExpr.Ident i
|
||||
|
||||
let createLet (bindings : SynBinding list) (body : SynExpr) : SynExpr =
|
||||
let inline createLongIdent (ident : string list) : SynExpr =
|
||||
SynExpr.CreateLongIdent (SynLongIdent.createS' ident)
|
||||
|
||||
let inline createLongIdent' (ident : Ident list) : SynExpr =
|
||||
SynExpr.CreateLongIdent (SynLongIdent.create ident)
|
||||
|
||||
let inline createLet (bindings : SynBinding list) (body : SynExpr) : SynExpr =
|
||||
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.CreateMatch (matchOn, cases)
|
||||
|
||||
let typeAnnotate (ty : SynType) (expr : SynExpr) : SynExpr = SynExpr.CreateTyped (expr, ty)
|
||||
|
||||
let inline paren (e : SynExpr) : SynExpr =
|
||||
SynExpr.Paren (e, range0, Some range0, 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 reraise : SynExpr = createIdent "reraise" |> applyTo (SynExpr.CreateConst ())
|
||||
|
||||
/// {compExpr} { {lets} ; return {ret} }
|
||||
let createCompExpr (compExpr : string) (retBody : SynExpr) (lets : CompExprBinding list) : SynExpr =
|
||||
let retStatement = SynExpr.YieldOrReturn ((false, true), retBody, range0)
|
||||
@@ -211,7 +243,7 @@ module internal SynExpr =
|
||||
DebugPointAtBinding.Yes range0,
|
||||
false,
|
||||
true,
|
||||
SynPat.CreateNamed (Ident.Create lhs),
|
||||
SynPat.named lhs,
|
||||
rhs,
|
||||
[],
|
||||
state,
|
||||
@@ -220,13 +252,12 @@ module internal SynExpr =
|
||||
EqualsRange = Some range0
|
||||
}
|
||||
)
|
||||
| Let (lhs, rhs) ->
|
||||
createLet [ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ] state
|
||||
| Let (lhs, rhs) -> createLet [ SynBinding.basic (SynLongIdent.createS lhs) [] rhs ] state
|
||||
| Use (lhs, rhs) ->
|
||||
SynExpr.LetOrUse (
|
||||
false,
|
||||
true,
|
||||
[ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ],
|
||||
[ SynBinding.basic (SynLongIdent.createS lhs) [] rhs ],
|
||||
state,
|
||||
range0,
|
||||
{
|
||||
@@ -243,17 +274,14 @@ module internal SynExpr =
|
||||
|
||||
/// {expr} |> Async.AwaitTask
|
||||
let awaitTask (expr : SynExpr) : SynExpr =
|
||||
expr
|
||||
|> pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "AwaitTask" ]))
|
||||
expr |> pipeThroughFunction (createLongIdent [ "Async" ; "AwaitTask" ])
|
||||
|
||||
/// {ident}.ToString ()
|
||||
/// with special casing for some types like DateTime
|
||||
let toString (ty : SynType) (ident : SynExpr) =
|
||||
match ty with
|
||||
| DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-dd")
|
||||
| DateTime ->
|
||||
ident
|
||||
|> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-ddTHH:mm:ss")
|
||||
| DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-dd")
|
||||
| DateTime -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-ddTHH:mm:ss")
|
||||
| _ -> callMethod "ToString" ident
|
||||
|
||||
let upcast' (ty : SynType) (e : SynExpr) = SynExpr.Upcast (e, ty, range0)
|
||||
@@ -275,8 +303,7 @@ module internal SynExpr =
|
||||
)
|
||||
|
||||
/// {ident} - {n}
|
||||
let minusN (ident : SynLongIdent) (n : int) : SynExpr =
|
||||
minus ident (SynExpr.CreateConst (SynConst.Int32 n))
|
||||
let minusN (ident : SynLongIdent) (n : int) : SynExpr = minus ident (SynExpr.CreateConst n)
|
||||
|
||||
/// {y} > {x}
|
||||
let greaterThan (x : SynExpr) (y : SynExpr) : SynExpr =
|
||||
|
83
WoofWare.Myriad.Plugins/SynExpr/SynLongIdent.fs
Normal file
83
WoofWare.Myriad.Plugins/SynExpr/SynLongIdent.fs
Normal file
@@ -0,0 +1,83 @@
|
||||
namespace WoofWare.Myriad.Plugins
|
||||
|
||||
open Fantomas.FCS.Text.Range
|
||||
open Fantomas.FCS.Syntax
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal SynLongIdent =
|
||||
|
||||
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)
|
@@ -8,3 +8,9 @@ module internal SynPat =
|
||||
|
||||
let annotateType (ty : SynType) (pat : SynPat) =
|
||||
SynPat.Paren (SynPat.Typed (pat, ty, range0), range0)
|
||||
|
||||
let named (s : string) : SynPat =
|
||||
SynPat.Named (SynIdent.SynIdent (Ident (s, range0), None), false, None, range0)
|
||||
|
||||
let namedI (i : Ident) : SynPat =
|
||||
SynPat.Named (SynIdent.SynIdent (i, None), false, None, range0)
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace WoofWare.Myriad.Plugins
|
||||
|
||||
open Fantomas.FCS.Syntax
|
||||
open Fantomas.FCS.Text.Range
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal SynType =
|
||||
@@ -8,3 +9,224 @@ module internal SynType =
|
||||
match ty with
|
||||
| SynType.Paren (ty, _) -> stripOptionalParen 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)
|
||||
|
||||
[<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>
|
||||
<Compile Include="List.fs"/>
|
||||
<Compile Include="Ident.fs" />
|
||||
<Compile Include="AstHelper.fs"/>
|
||||
<Compile Include="Primitives.fs" />
|
||||
<Compile Include="SynExpr\PreXmlDoc.fs" />
|
||||
<Compile Include="SynExpr\Ident.fs" />
|
||||
<Compile Include="SynExpr\SynLongIdent.fs" />
|
||||
<Compile Include="SynExpr\SynExprLetOrUseTrivia.fs" />
|
||||
<Compile Include="SynExpr\SynBinding.fs" />
|
||||
<Compile Include="SynExpr\SynExpr.fs" />
|
||||
<Compile Include="SynExpr\SynType.fs" />
|
||||
<Compile Include="SynExpr\SynMatchClause.fs" />
|
||||
<Compile Include="SynExpr\SynPat.fs" />
|
||||
<Compile Include="SynExpr\CompExpr.fs" />
|
||||
<Compile Include="SynExpr\SynExpr.fs" />
|
||||
<Compile Include="SynExpr\SynAttribute.fs" />
|
||||
<Compile Include="SynExpr\SynArgPats.fs" />
|
||||
<Compile Include="SynExpr\SynField.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="AstHelper.fs" />
|
||||
<Compile Include="RemoveOptionsGenerator.fs"/>
|
||||
<Compile Include="InterfaceMockGenerator.fs"/>
|
||||
<Compile Include="JsonSerializeGenerator.fs"/>
|
||||
|
Reference in New Issue
Block a user