mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-06 20:48:40 +00:00
Add JSON parse source gen (#9)
This commit is contained in:
@@ -1,29 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<MyriadSdkGenerator Include="$(MSBuildThisFileDirectory)..\MyriadPlugin\bin\$(Configuration)\$(TargetFramework)\MyriadPlugin.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="RecordFile.fs" />
|
||||
<Compile Include="Generated.fs"> <!--1-->
|
||||
<MyriadFile>RecordFile.fs</MyriadFile> <!--2-->
|
||||
</Compile>
|
||||
<Compile Include="Program.fs" />
|
||||
<None Include="..\runmyriad.sh">
|
||||
<Link>runmyriad.sh</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MyriadPlugin\MyriadPlugin.fsproj" />
|
||||
<PackageReference Include="Myriad.Sdk" Version="0.8.3" />
|
||||
<PackageReference Include="Myriad.Core" Version="0.8.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<MyriadSdkGenerator Include="$(MSBuildThisFileDirectory)..\MyriadPlugin\bin\$(Configuration)\net6.0\MyriadPlugin.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="myriad.toml" />
|
||||
<Compile Include="RecordFile.fs" />
|
||||
<Compile Include="GeneratedRecord.fs"> <!--1-->
|
||||
<MyriadFile>RecordFile.fs</MyriadFile> <!--2-->
|
||||
</Compile>
|
||||
<Compile Include="JsonRecord.fs" />
|
||||
<Compile Include="GeneratedJson.fs"> <!--1-->
|
||||
<MyriadFile>JsonRecord.fs</MyriadFile> <!--2-->
|
||||
</Compile>
|
||||
<None Include="..\runmyriad.sh">
|
||||
<Link>runmyriad.sh</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MyriadPlugin\MyriadPlugin.fsproj" />
|
||||
<PackageReference Include="Myriad.Sdk" Version="0.8.3" />
|
||||
<PackageReference Include="Myriad.Core" Version="0.8.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@@ -22,7 +22,7 @@ module RecordType =
|
||||
/// Remove the optional members of the input.
|
||||
let shorten (input : RecordType) : Short =
|
||||
{
|
||||
A = input.A |> Option.defaultWith RecordType.DefaultA
|
||||
A = input.A |> Option.defaultValue (RecordType.DefaultA ())
|
||||
B = input.B
|
||||
C = input.C
|
||||
}
|
43
ConsumePlugin/GeneratedJson.fs
Normal file
43
ConsumePlugin/GeneratedJson.fs
Normal file
@@ -0,0 +1,43 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// This code was generated by myriad.
|
||||
// Changes to this file will be lost when the code is regenerated.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the InnerType type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module InnerType =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType =
|
||||
let Thing = node.[(Literals.something)].AsValue().GetValue<string> ()
|
||||
|
||||
{
|
||||
Thing = Thing
|
||||
}
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the JsonRecordType type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module JsonRecordType =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType =
|
||||
let D = InnerType.jsonParse node.["d"]
|
||||
|
||||
let C =
|
||||
node.["hi"].AsArray ()
|
||||
|> Seq.map (fun elt -> elt.GetValue<int> ())
|
||||
|> List.ofSeq
|
||||
|
||||
let B2 = node.["another-thing"].AsValue ()
|
||||
let B = B2.GetValue<string> ()
|
||||
let A = node.["a"].AsValue().GetValue<int> ()
|
||||
|
||||
{
|
||||
A = A
|
||||
B = B
|
||||
C = C
|
||||
D = D
|
||||
}
|
28
ConsumePlugin/GeneratedRecord.fs
Normal file
28
ConsumePlugin/GeneratedRecord.fs
Normal file
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// This code was generated by myriad.
|
||||
// Changes to this file will be lost when the code is regenerated.
|
||||
//------------------------------------------------------------------------------
|
||||
namespace ConsumePlugin
|
||||
|
||||
/// Module containing an option-truncated version of the RecordType type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module RecordType =
|
||||
/// My whatnot
|
||||
type Short =
|
||||
{
|
||||
/// A thing!
|
||||
A : int
|
||||
/// Another thing!
|
||||
B : string
|
||||
/// Yet another thing!
|
||||
C : float list
|
||||
}
|
||||
|
||||
/// Remove the optional members of the input.
|
||||
let shorten (input : RecordType) : Short =
|
||||
{
|
||||
A = input.A |> Option.defaultWith RecordType.DefaultA
|
||||
B = input.B
|
||||
C = input.C
|
||||
}
|
28
ConsumePlugin/JsonRecord.fs
Normal file
28
ConsumePlugin/JsonRecord.fs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace ConsumePlugin
|
||||
|
||||
open System.Text.Json.Serialization
|
||||
|
||||
module Literals =
|
||||
[<Literal>]
|
||||
let something = "something"
|
||||
|
||||
[<MyriadPlugin.JsonParse>]
|
||||
type InnerType =
|
||||
{
|
||||
[<JsonPropertyName(Literals.something)>]
|
||||
Thing : string
|
||||
}
|
||||
|
||||
/// My whatnot
|
||||
[<MyriadPlugin.JsonParse>]
|
||||
type JsonRecordType =
|
||||
{
|
||||
/// A thing!
|
||||
A : int
|
||||
/// Another thing!
|
||||
[<JsonPropertyName "another-thing">]
|
||||
B : string
|
||||
[<System.Text.Json.Serialization.JsonPropertyName "hi">]
|
||||
C : int list
|
||||
D : InnerType
|
||||
}
|
@@ -1,6 +1,4 @@
|
||||
namespace UsePlugin
|
||||
|
||||
open System
|
||||
namespace ConsumePlugin
|
||||
|
||||
type ParseState =
|
||||
| AwaitingKey
|
@@ -1,6 +1,6 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "UsePlugin", "UsePlugin\UsePlugin.fsproj", "{0D174482-9CB2-448A-8BA8-846FAEC65579}"
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ConsumePlugin", "ConsumePlugin\ConsumePlugin.fsproj", "{0D174482-9CB2-448A-8BA8-846FAEC65579}"
|
||||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MyriadPlugin", "MyriadPlugin\MyriadPlugin.fsproj", "{DB86C53B-4090-4791-884B-024C5759855F}"
|
||||
EndProject
|
||||
|
@@ -9,12 +9,16 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="TestSurface.fs" />
|
||||
<Compile Include="TestRemoveOptions.fs" />
|
||||
<Compile Include="TestJsonParse.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ApiSurface" Version="4.0.8" />
|
||||
<PackageReference Include="ApiSurface" Version="4.0.25" />
|
||||
<PackageReference Include="FsCheck" Version="2.16.6" />
|
||||
<PackageReference Include="FsUnit" Version="5.6.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit" Version="3.14.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
@@ -22,6 +26,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MyriadPlugin\MyriadPlugin.fsproj" />
|
||||
<ProjectReference Include="..\ConsumePlugin\ConsumePlugin.fsproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
31
MyriadPlugin.Test/TestJsonParse.fs
Normal file
31
MyriadPlugin.Test/TestJsonParse.fs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace MyriadPlugin.Test
|
||||
|
||||
open System.Text.Json.Nodes
|
||||
open ConsumePlugin
|
||||
open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
|
||||
[<TestFixture>]
|
||||
module TestJsonParse =
|
||||
[<Test>]
|
||||
let ``Single example`` () =
|
||||
let s =
|
||||
"""
|
||||
{
|
||||
"a": 3, "another-thing": "hello", "hi": [6, 1], "d": {"something": "oh hi"}
|
||||
}
|
||||
"""
|
||||
|
||||
let expected =
|
||||
{
|
||||
A = 3
|
||||
B = "hello"
|
||||
C = [ 6 ; 1 ]
|
||||
D =
|
||||
{
|
||||
Thing = "oh hi"
|
||||
}
|
||||
}
|
||||
|
||||
let actual = s |> JsonNode.Parse |> JsonRecordType.jsonParse
|
||||
actual |> shouldEqual expected
|
24
MyriadPlugin.Test/TestRemoveOptions.fs
Normal file
24
MyriadPlugin.Test/TestRemoveOptions.fs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace MyriadPlugin.Test
|
||||
|
||||
open FsCheck
|
||||
open ConsumePlugin
|
||||
open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
|
||||
module TestRemoveOptions =
|
||||
|
||||
let shortenProperty (f : RecordType) =
|
||||
let g = RecordType.shorten f
|
||||
|
||||
g.B |> shouldEqual f.B
|
||||
g.C |> shouldEqual f.C
|
||||
|
||||
match f.A with
|
||||
| None -> g.A |> shouldEqual (RecordType.DefaultA ())
|
||||
| Some a -> g.A |> shouldEqual a
|
||||
|
||||
true
|
||||
|
||||
[<Test>]
|
||||
let ``shorten works`` () =
|
||||
Check.QuickThrowOnFailure shortenProperty
|
86
MyriadPlugin/AstHelper.fs
Normal file
86
MyriadPlugin/AstHelper.fs
Normal file
@@ -0,0 +1,86 @@
|
||||
namespace MyriadPlugin
|
||||
|
||||
open Fantomas.FCS.Syntax
|
||||
open Fantomas.FCS.SyntaxTrivia
|
||||
open Fantomas.FCS.Text.Range
|
||||
open Fantomas.FCS.Xml
|
||||
open Myriad.Core.AstExtensions
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal AstHelper =
|
||||
|
||||
let constructRecord (fields : (RecordFieldName * SynExpr option) list) : SynExpr =
|
||||
let fields =
|
||||
fields
|
||||
|> List.map (fun (rfn, synExpr) -> SynExprRecordField (rfn, Some range0, synExpr, None))
|
||||
|
||||
SynExpr.Record (None, None, fields, range0)
|
||||
|
||||
let private createRecordType
|
||||
(
|
||||
name : Ident,
|
||||
repr : SynTypeDefnRepr,
|
||||
members : SynMemberDefns,
|
||||
xmldoc : PreXmlDoc
|
||||
)
|
||||
: SynTypeDefn
|
||||
=
|
||||
let name = SynComponentInfo.Create ([ name ], xmldoc = xmldoc)
|
||||
|
||||
let trivia : SynTypeDefnTrivia =
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
EqualsRange = Some range0
|
||||
WithKeyword = Some range0
|
||||
}
|
||||
|
||||
SynTypeDefn (name, repr, members, None, range0, trivia)
|
||||
|
||||
let defineRecordType
|
||||
(
|
||||
name : Ident,
|
||||
fields : SynField seq,
|
||||
members : SynMemberDefns option,
|
||||
xmldoc : PreXmlDoc option
|
||||
)
|
||||
: SynTypeDefn
|
||||
=
|
||||
let repr =
|
||||
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, Seq.toList fields, range0), range0)
|
||||
|
||||
createRecordType (name, repr, defaultArg members SynMemberDefns.Empty, defaultArg xmldoc PreXmlDoc.Empty)
|
||||
|
||||
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 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
|
||||
|
||||
[<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 (|ListType|_|) (fieldType : SynType) =
|
||||
match fieldType with
|
||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isListIdent ident ->
|
||||
Some innerType
|
||||
| _ -> None
|
||||
|
||||
/// Returns the string name of the type.
|
||||
let (|PrimitiveType|_|) (fieldType : SynType) =
|
||||
match fieldType with
|
||||
| SynType.LongIdent ident ->
|
||||
match ident.LongIdent with
|
||||
| [ i ] -> [ "string" ; "float" ; "int" ] |> List.tryFind (fun s -> s = i.idText)
|
||||
| _ -> None
|
||||
| _ -> None
|
385
MyriadPlugin/JsonParseGenerator.fs
Normal file
385
MyriadPlugin/JsonParseGenerator.fs
Normal file
@@ -0,0 +1,385 @@
|
||||
namespace MyriadPlugin
|
||||
|
||||
open System
|
||||
open System.Text
|
||||
open Fantomas.FCS.Syntax
|
||||
open Fantomas.FCS.SyntaxTrivia
|
||||
open Fantomas.FCS.Xml
|
||||
open Myriad.Core
|
||||
|
||||
/// Attribute indicating a record type to which the "Add JSON parse" Myriad
|
||||
/// generator should apply during build.
|
||||
type JsonParseAttribute () =
|
||||
inherit Attribute ()
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal JsonParseGenerator =
|
||||
open Fantomas.FCS.Text.Range
|
||||
open Myriad.Core.Ast
|
||||
|
||||
let createParseLineValue (propertyName : SynExpr) (typeName : string) : SynExpr =
|
||||
// node.["town"].AsValue().GetValue<string> ()
|
||||
let indexed =
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.DotGet (
|
||||
SynExpr.DotIndexedGet (SynExpr.Ident (Ident.Create "node"), propertyName, range0, range0),
|
||||
range0,
|
||||
SynLongIdent.SynLongIdent (id = [ Ident.Create "AsValue" ], dotRanges = [], trivia = [ None ]),
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateConst (SynConst.Unit)
|
||||
)
|
||||
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.TypeApp (
|
||||
SynExpr.DotGet (
|
||||
indexed,
|
||||
range0,
|
||||
SynLongIdent.SynLongIdent (id = [ Ident.Create "GetValue" ], dotRanges = [], trivia = [ None ]),
|
||||
range0
|
||||
),
|
||||
range0,
|
||||
[
|
||||
SynType.LongIdent (
|
||||
SynLongIdent.SynLongIdent (id = [ Ident.Create typeName ], dotRanges = [], trivia = [ None ])
|
||||
)
|
||||
],
|
||||
[],
|
||||
Some range0,
|
||||
range0,
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
)
|
||||
|
||||
let createParseLineCallThrough (propertyName : SynExpr) (fieldType : SynType) : SynExpr =
|
||||
// Type.jsonParse node.["town"]
|
||||
let typeName =
|
||||
match fieldType with
|
||||
| SynType.LongIdent ident -> ident.LongIdent
|
||||
| _ -> failwith $"Unrecognised type: %+A{fieldType}"
|
||||
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (typeName @ [ Ident.Create "jsonParse" ])),
|
||||
SynExpr.DotIndexedGet (SynExpr.CreateIdentString "node", propertyName, range0, range0)
|
||||
)
|
||||
|
||||
/// collectionType is e.g. "List"; we'll be calling `ofSeq` on it.
|
||||
let createParseLineList (collectionType : string) (propertyName : SynExpr) (elementType : string) : SynExpr =
|
||||
// node.["openingHours"].AsArray()
|
||||
// |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
||||
// |> List.ofSeq
|
||||
|
||||
let parsedDataPat = [ SynPat.CreateNamed (Ident.Create "elt") ]
|
||||
|
||||
let parsedData =
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.TypeApp (
|
||||
SynExpr.DotGet (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"),
|
||||
range0,
|
||||
SynLongIdent.Create [ "GetValue" ],
|
||||
range0
|
||||
),
|
||||
range0,
|
||||
[ SynType.CreateLongIdent elementType ],
|
||||
[],
|
||||
Some range0,
|
||||
range0,
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
)
|
||||
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateAppInfix (
|
||||
SynExpr.LongIdent (
|
||||
false,
|
||||
SynLongIdent.SynLongIdent (
|
||||
[ Ident.Create "op_PipeRight" ],
|
||||
[],
|
||||
[ Some (IdentTrivia.OriginalNotation "|>") ]
|
||||
),
|
||||
None,
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateAppInfix (
|
||||
SynExpr.LongIdent (
|
||||
false,
|
||||
SynLongIdent.SynLongIdent (
|
||||
[ Ident.Create "op_PipeRight" ],
|
||||
[],
|
||||
[ Some (IdentTrivia.OriginalNotation "|>") ]
|
||||
),
|
||||
None,
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.DotGet (
|
||||
SynExpr.DotIndexedGet (
|
||||
SynExpr.CreateIdent (Ident.Create "node"),
|
||||
propertyName,
|
||||
range0,
|
||||
range0
|
||||
),
|
||||
range0,
|
||||
SynLongIdent.CreateString "AsArray",
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
)
|
||||
),
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
||||
SynExpr.CreateParen (
|
||||
SynExpr.Lambda (
|
||||
false,
|
||||
false,
|
||||
SynSimplePats.Create [ SynSimplePat.CreateId (Ident.Create "elt") ],
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.TypeApp (
|
||||
SynExpr.DotGet (
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
),
|
||||
range0,
|
||||
SynLongIdent.CreateString "GetValue",
|
||||
range0
|
||||
),
|
||||
range0,
|
||||
[ SynType.CreateLongIdent (SynLongIdent.CreateString elementType) ],
|
||||
[],
|
||||
None,
|
||||
range0,
|
||||
range0
|
||||
),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
),
|
||||
Some (parsedDataPat, parsedData),
|
||||
range0,
|
||||
{
|
||||
ArrowRange = Some range0
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ collectionType ; "ofSeq" ])
|
||||
)
|
||||
|
||||
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
||||
let createParseRhs (varName : string) (propertyName : SynExpr) (fieldType : SynType) : SynExpr =
|
||||
match fieldType with
|
||||
| OptionType ty -> failwith "TODO: options"
|
||||
| PrimitiveType typeName -> createParseLineValue propertyName typeName
|
||||
| ListType (PrimitiveType typeName) -> createParseLineList "List" propertyName typeName
|
||||
// TODO: support recursive lists
|
||||
| _ ->
|
||||
// Let's just hope that we've also got our own type annotation!
|
||||
createParseLineCallThrough propertyName fieldType
|
||||
|
||||
let createMaker (typeName : LongIdent) (fields : SynField list) =
|
||||
let xmlDoc = PreXmlDoc.Create " Parse from a JSON node."
|
||||
|
||||
let returnInfo =
|
||||
SynBindingReturnInfo.Create (SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName))
|
||||
|
||||
let inputArg = Ident.Create "node"
|
||||
let functionName = Ident.Create "jsonParse"
|
||||
|
||||
let inputVal =
|
||||
SynValData.SynValData (
|
||||
None,
|
||||
SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty),
|
||||
Some inputArg
|
||||
)
|
||||
|
||||
let assignments =
|
||||
fields
|
||||
|> List.map (fun (SynField (attrs, _, id, fieldType, _, _, _, _, _)) ->
|
||||
let id =
|
||||
match id with
|
||||
| None -> failwith "didn't get an ID on field"
|
||||
| Some id -> id
|
||||
|
||||
let propertyNameAttr =
|
||||
attrs
|
||||
|> List.collect (fun l -> l.Attributes)
|
||||
|> List.tryFind (fun attr ->
|
||||
attr.TypeName.AsString.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||
)
|
||||
|
||||
let propertyName =
|
||||
match propertyNameAttr with
|
||||
| None ->
|
||||
let sb = StringBuilder id.idText.Length
|
||||
sb.Append (Char.ToLowerInvariant id.idText.[0]) |> ignore
|
||||
|
||||
if id.idText.Length > 1 then
|
||||
sb.Append id.idText.[1..] |> ignore
|
||||
|
||||
sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst
|
||||
| Some name -> name.ArgExpr
|
||||
|
||||
let pattern =
|
||||
SynPat.LongIdent (
|
||||
SynLongIdent.CreateFromLongIdent [ id ],
|
||||
None,
|
||||
None,
|
||||
SynArgPats.Empty,
|
||||
None,
|
||||
range0
|
||||
)
|
||||
|
||||
SynBinding.Let (
|
||||
isInline = false,
|
||||
isMutable = false,
|
||||
expr = createParseRhs (id.ToString ()) propertyName fieldType,
|
||||
valData = inputVal,
|
||||
pattern = pattern
|
||||
)
|
||||
)
|
||||
|
||||
let finalConstruction =
|
||||
fields
|
||||
|> List.map (fun (SynField (_, _, id, _, _, _, _, _, _)) ->
|
||||
let id =
|
||||
match id with
|
||||
| None -> failwith "Expected record field to have an identifying name"
|
||||
| Some id -> id
|
||||
|
||||
(SynLongIdent.CreateFromLongIdent [ id ], true),
|
||||
Some (SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ id ]))
|
||||
)
|
||||
|> AstHelper.constructRecord
|
||||
|
||||
let assignments =
|
||||
(finalConstruction, assignments)
|
||||
||> List.fold (fun final assignment ->
|
||||
SynExpr.LetOrUse (
|
||||
false,
|
||||
false,
|
||||
[ assignment ],
|
||||
final,
|
||||
range0,
|
||||
{
|
||||
InKeyword = None
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
let pattern =
|
||||
SynPat.LongIdent (
|
||||
SynLongIdent.CreateFromLongIdent [ functionName ],
|
||||
None,
|
||||
None,
|
||||
SynArgPats.Pats
|
||||
[
|
||||
SynPat.CreateTyped (
|
||||
SynPat.CreateNamed inputArg,
|
||||
SynType.LongIdent (
|
||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||
)
|
||||
)
|
||||
|> SynPat.CreateParen
|
||||
],
|
||||
None,
|
||||
range0
|
||||
)
|
||||
|
||||
let binding =
|
||||
SynBinding.Let (
|
||||
isInline = false,
|
||||
isMutable = false,
|
||||
xmldoc = xmlDoc,
|
||||
returnInfo = returnInfo,
|
||||
expr = assignments,
|
||||
valData = inputVal,
|
||||
pattern = pattern
|
||||
)
|
||||
|
||||
SynModuleDecl.CreateLet [ binding ]
|
||||
|
||||
let createRecordModule (namespaceId : LongIdent) (typeDefn : SynTypeDefn) =
|
||||
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||
typeDefn
|
||||
|
||||
let (SynComponentInfo (_attributes, _typeParams, _constraints, recordId, _, _preferPostfix, _access, _)) =
|
||||
synComponentInfo
|
||||
|
||||
match synTypeDefnRepr with
|
||||
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, recordFields, _recordRange), _) ->
|
||||
|
||||
let decls = [ createMaker recordId recordFields ]
|
||||
|
||||
let compilationRepresentation : SynAttribute =
|
||||
{
|
||||
TypeName = SynLongIdent.CreateString "CompilationRepresentation"
|
||||
ArgExpr =
|
||||
SynExpr.CreateLongIdent (
|
||||
false,
|
||||
SynLongIdent.Create [ "CompilationRepresentationFlags" ; "ModuleSuffix" ],
|
||||
None
|
||||
)
|
||||
|> SynExpr.CreateParen
|
||||
Target = None
|
||||
AppliesToGetterAndSetter = false
|
||||
Range = range0
|
||||
}
|
||||
|
||||
let attributes =
|
||||
[
|
||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
||||
SynAttributeList.Create compilationRepresentation
|
||||
]
|
||||
|
||||
let xmlDoc =
|
||||
recordId
|
||||
|> Seq.map (fun i -> i.idText)
|
||||
|> String.concat "."
|
||||
|> sprintf " Module containing JSON parsing methods for the %s type"
|
||||
|> PreXmlDoc.Create
|
||||
|
||||
let info =
|
||||
SynComponentInfo.Create (recordId, attributes = attributes, xmldoc = xmlDoc)
|
||||
|
||||
let mdl = SynModuleDecl.CreateNestedModule (info, decls)
|
||||
|
||||
SynModuleOrNamespace.CreateNamespace (namespaceId, decls = [ mdl ])
|
||||
| _ -> failwithf "Not a record type"
|
||||
|
||||
/// Myriad generator that provides a JSON parse function for a record type.
|
||||
[<MyriadGenerator("json-parse")>]
|
||||
type JsonParseGenerator () =
|
||||
|
||||
interface IMyriadGenerator with
|
||||
member _.ValidInputExtensions = [ ".fs" ]
|
||||
|
||||
member _.Generate (context : GeneratorContext) =
|
||||
let ast, _ =
|
||||
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
|
||||
|
||||
let records = Ast.extractRecords ast
|
||||
|
||||
let namespaceAndRecords =
|
||||
records
|
||||
|> List.choose (fun (ns, types) ->
|
||||
match types |> List.filter Ast.hasAttribute<JsonParseAttribute> with
|
||||
| [] -> None
|
||||
| types -> Some (ns, types)
|
||||
)
|
||||
|
||||
let modules =
|
||||
namespaceAndRecords
|
||||
|> List.collect (fun (ns, records) ->
|
||||
records
|
||||
|> List.map (fun record ->
|
||||
let recordModule = JsonParseGenerator.createRecordModule ns record
|
||||
recordModule
|
||||
)
|
||||
)
|
||||
|
||||
Output.Ast modules
|
@@ -1,17 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<Authors>Patrick Stevens</Authors>
|
||||
<Copyright>Copyright (c) Patrick Stevens 2023</Copyright>
|
||||
<Description>Provides some Myriad compile-time code generation plugins.</Description>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageTags>myriad;fsharp;source-generator;source-gen;json</PackageTags>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarnOn>FS3559</WarnOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Myriad.Core" Version="0.8.3" />
|
||||
<PackageReference Update="FSharp.Core" Version="6.0.6" />
|
||||
<!-- the lowest version allowed by Myriad.Core -->
|
||||
<PackageReference Update="FSharp.Core" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="AstHelper.fs" />
|
||||
<Compile Include="RemoveOptionsGenerator.fs" />
|
||||
<Compile Include="JsonParseGenerator.fs" />
|
||||
<None Include="version.json" />
|
||||
<EmbeddedResource Include="SurfaceBaseline.txt" />
|
||||
</ItemGroup>
|
||||
|
@@ -11,47 +11,11 @@ open Myriad.Core
|
||||
type RemoveOptionsAttribute () =
|
||||
inherit Attribute ()
|
||||
|
||||
module internal Create =
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal RemoveOptionsGenerator =
|
||||
open Fantomas.FCS.Text.Range
|
||||
open Myriad.Core.Ast
|
||||
|
||||
let createRecordMyriad fields =
|
||||
// TODO: this first equals-None requires a range
|
||||
let fields =
|
||||
fields
|
||||
|> List.map (fun (rfn, synExpr) -> SynExprRecordField (rfn, Some range0, synExpr, None))
|
||||
|
||||
SynExpr.Record (None, None, fields, range0)
|
||||
|
||||
let createFromRepr (name : Ident, repr : SynTypeDefnRepr, members : SynMemberDefns, xmldoc : PreXmlDoc) =
|
||||
let name = SynComponentInfo.Create ([ name ], xmldoc = xmldoc)
|
||||
|
||||
let trivia : SynTypeDefnTrivia =
|
||||
{
|
||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||
EqualsRange = Some range0
|
||||
WithKeyword = Some range0
|
||||
}
|
||||
|
||||
SynTypeDefn (name, repr, members, None, range0, trivia)
|
||||
|
||||
let createRecord (name : Ident, fields : SynField seq, members : SynMemberDefns option, xmldoc : PreXmlDoc option) =
|
||||
let repr =
|
||||
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, Seq.toList fields, range0), range0)
|
||||
|
||||
createFromRepr (name, repr, defaultArg members SynMemberDefns.Empty, defaultArg xmldoc PreXmlDoc.Empty)
|
||||
|
||||
let isOptionIdent (ident : SynLongIdent) : bool =
|
||||
match ident.LongIdent with
|
||||
| [ i ] when String.Equals (i.idText, "option", StringComparison.OrdinalIgnoreCase) -> true
|
||||
// TODO: consider Microsoft.FSharp.Option or whatever it is
|
||||
| _ -> false
|
||||
|
||||
let (|OptionType|_|) (fieldType : SynType) =
|
||||
match fieldType with
|
||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when isOptionIdent ident -> Some innerType
|
||||
| _ -> None
|
||||
|
||||
let private removeOption (s : SynField) : SynField =
|
||||
let (SynField.SynField (synAttributeLists,
|
||||
isStatic,
|
||||
@@ -88,8 +52,8 @@ module internal Create =
|
||||
|
||||
let typeDecl : SynTypeDefn =
|
||||
match xmlDoc with
|
||||
| None -> createRecord (name, fields, None, None)
|
||||
| Some xmlDoc -> createRecord (name, fields, None, Some xmlDoc)
|
||||
| None -> AstHelper.defineRecordType (name, fields, None, None)
|
||||
| Some xmlDoc -> AstHelper.defineRecordType (name, fields, None, Some xmlDoc)
|
||||
|
||||
SynModuleDecl.Types ([ typeDecl ], range0)
|
||||
|
||||
@@ -150,7 +114,7 @@ module internal Create =
|
||||
|
||||
(SynLongIdent.CreateFromLongIdent [ id ], true), Some body
|
||||
)
|
||||
|> createRecordMyriad
|
||||
|> AstHelper.constructRecord
|
||||
|
||||
let pattern =
|
||||
SynPat.LongIdent (
|
||||
@@ -261,7 +225,7 @@ type RemoveOptionsGenerator () =
|
||||
|> List.collect (fun (ns, records) ->
|
||||
records
|
||||
|> List.map (fun record ->
|
||||
let recordModule = Create.createRecordModule ns record
|
||||
let recordModule = RemoveOptionsGenerator.createRecordModule ns record
|
||||
recordModule
|
||||
)
|
||||
)
|
||||
|
@@ -1,3 +1,7 @@
|
||||
MyriadPlugin.JsonParseAttribute inherit System.Attribute
|
||||
MyriadPlugin.JsonParseAttribute..ctor [constructor]: unit
|
||||
MyriadPlugin.JsonParseGenerator inherit obj, implements Myriad.Core.IMyriadGenerator
|
||||
MyriadPlugin.JsonParseGenerator..ctor [constructor]: unit
|
||||
MyriadPlugin.RemoveOptionsAttribute inherit System.Attribute
|
||||
MyriadPlugin.RemoveOptionsAttribute..ctor [constructor]: unit
|
||||
MyriadPlugin.RemoveOptionsGenerator inherit obj, implements Myriad.Core.IMyriadGenerator
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": "0.1",
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/main$"
|
||||
],
|
||||
"pathFilters": null
|
||||
}
|
||||
{
|
||||
"version": "0.2",
|
||||
"publicReleaseRefSpec": [
|
||||
"^refs/heads/main$"
|
||||
],
|
||||
"pathFilters": null
|
||||
}
|
||||
|
57
README.md
57
README.md
@@ -29,3 +29,60 @@ module Foo =
|
||||
```
|
||||
|
||||
(This is a proof of concept. It would be better to somehow disambiguate the module name.)
|
||||
|
||||
## `JsonParse`
|
||||
|
||||
Takes records like this:
|
||||
|
||||
```fsharp
|
||||
[<MyriadPlugin.JsonParse>]
|
||||
type InnerType =
|
||||
{
|
||||
[<JsonPropertyName "something">]
|
||||
Thing : string
|
||||
}
|
||||
|
||||
/// My whatnot
|
||||
[<MyriadPlugin.JsonParse>]
|
||||
type JsonRecordType =
|
||||
{
|
||||
/// A thing!
|
||||
A : int
|
||||
/// Another thing!
|
||||
B : string
|
||||
[<System.Text.Json.Serialization.JsonPropertyName "hi">]
|
||||
C : int list
|
||||
D : InnerType
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
and stamps out parsing methods like this:
|
||||
|
||||
```fsharp
|
||||
|
||||
/// Module containing JSON parsing methods for the InnerType type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module InnerType =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : InnerType =
|
||||
let Thing = node.["something"].AsValue().GetValue<string>()
|
||||
{ Thing = Thing }
|
||||
namespace UsePlugin
|
||||
|
||||
/// Module containing JSON parsing methods for the JsonRecordType type
|
||||
[<RequireQualifiedAccess>]
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module JsonRecordType =
|
||||
/// Parse from a JSON node.
|
||||
let jsonParse (node: System.Text.Json.Nodes.JsonNode) : JsonRecordType =
|
||||
let D = InnerType.jsonParse node.["d"]
|
||||
|
||||
let C =
|
||||
node.["hi"].AsArray() |> Seq.map (fun elt -> elt.GetValue<int>()) |> List.ofSeq
|
||||
|
||||
let B = node.["b"].AsValue().GetValue<string>()
|
||||
let A = node.["a"].AsValue().GetValue<int>()
|
||||
{ A = A; B = B; C = C; D = D }
|
||||
```
|
||||
|
@@ -1,26 +0,0 @@
|
||||
namespace UsePlugin
|
||||
|
||||
module Program =
|
||||
let f : RecordType =
|
||||
{
|
||||
A = Some 300
|
||||
B = "hello"
|
||||
C = [ 0.3 ]
|
||||
}
|
||||
|
||||
let g = RecordType.shorten f
|
||||
|
||||
[<EntryPoint>]
|
||||
let main _ =
|
||||
if not (f.B = g.B && f.C = g.C) then
|
||||
failwith "Non-optional fields differed"
|
||||
|
||||
match f.A with
|
||||
| None ->
|
||||
if g.A <> RecordType.DefaultA () then
|
||||
failwith "Couldn't acquire default"
|
||||
| Some a ->
|
||||
if a <> g.A then
|
||||
failwith "Didn't match existing f.A"
|
||||
|
||||
0
|
@@ -48,7 +48,7 @@
|
||||
src = ./nix/fetchDeps.sh;
|
||||
pname = pname;
|
||||
binPath = pkgs.lib.makeBinPath [pkgs.coreutils dotnet-sdk (pkgs.nuget-to-nix.override {inherit dotnet-sdk;})];
|
||||
projectFiles = toString ["./MyriadPlugin/MyriadPlugin.fsproj" "./UsePlugin/UsePlugin.fsproj"];
|
||||
projectFiles = toString ["./MyriadPlugin/MyriadPlugin.fsproj" "./ConsumePlugin/ConsumePlugin.fsproj"];
|
||||
testProjectFiles = ["./MyriadPlugin.Test/MyriadPlugin.Test.fsproj"];
|
||||
rids = pkgs.lib.concatStringsSep "\" \"" runtimeIds;
|
||||
packages = dotnet-sdk.packages;
|
||||
|
149
nix/deps.nix
149
nix/deps.nix
@@ -8,8 +8,8 @@
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "ApiSurface";
|
||||
version = "4.0.8";
|
||||
sha256 = "0xf3kp9lzi1bgm3c1h4lclvf1nvbn3cy5zfmys3i58h9c71yfsak";
|
||||
version = "4.0.25";
|
||||
sha256 = "0zjq8an9cr0l7wxdmm9n9s3iyq5m0zl4x0h0wmy5cz7am8y15qc4";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "coverlet.collector";
|
||||
@@ -26,41 +26,81 @@
|
||||
version = "6.1.1";
|
||||
sha256 = "0733dm5zjdp8w5wwalqlv1q52pghfr04863i9wy807f4qfd7rrin";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FsCheck";
|
||||
version = "2.16.6";
|
||||
sha256 = "176rwky6b5rk8dzldiz4068p7m9c5y9ygzbhadrs14jkl94pc56n";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "6.0.6";
|
||||
sha256 = "1mb1rwzs48c124pqxymnjgv6g3r6zb8n1v953hflcf20nq6yxi77";
|
||||
version = "6.0.1";
|
||||
sha256 = "0qks2aadkhsffg9a6xq954ll9xacnph852avd7ljh9n2g6vj06qj";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "8.0.100";
|
||||
sha256 = "06z3vg8yj7i83x6gmnzl2lka1bp4hzc07h6mrydpilxswnmy2a0l";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FsUnit";
|
||||
version = "5.6.1";
|
||||
sha256 = "1zffn9dm2c44v8qjzwfg6y3psydiv2bn3n305rf7mc57cmm4ygv3";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Ref";
|
||||
version = "6.0.25";
|
||||
sha256 = "1vrmqn5j6ibwkqasbf7x7n4w5jdclnz3giymiwvym2wa0y5zc59q";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Ref";
|
||||
version = "8.0.0";
|
||||
sha256 = "0k304yhpm92c46a1fscbzlgvdbhrm9vlbpyfgwp3cafz4f7z7a5y";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
||||
version = "6.0.25";
|
||||
sha256 = "0mgcs4si7mwd0f555s1vg17pf4nqfaijd1pci359l1pgrmv70rrg";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
||||
version = "8.0.0";
|
||||
sha256 = "05y1xb5fw8lzvb4si77a5qwfwfz1855crqbphrwky6x9llivbhkx";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "0wvzhqhlmlbnpa18qp8m3wcrlcgj3ckvp3iv2n7g8vb60c3238aq";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
||||
version = "8.0.0";
|
||||
sha256 = "18zdbcb2bn7wy1dp14z5jyqiiwr9rkad1lcb158r5ikjfq1rg5iw";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
||||
version = "6.0.25";
|
||||
sha256 = "1pywgvb8ck1d5aadmijd5s3z6yclchd9pa6dsahijmm55ibplx36";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
||||
version = "8.0.0";
|
||||
sha256 = "1nbxzmj6cnccylxis67c54c0ik38ma4rwdvgg6sxd6r04219maqm";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "1zlf0w7i6r02719dv3nw4jy14sa0rs53i89an5alz5qmywdy3f1d";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
||||
version = "8.0.0";
|
||||
sha256 = "1wqkbjd1ywv9w397l7rsb89mijc5n0hv7jq9h09xfz6wn9qsp152";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.win-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "1fbsnm4056cpd4avgpi5sq05m1yd9k4x229ckxpr4q7yc94sncwy";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.win-x64";
|
||||
version = "8.0.0";
|
||||
@@ -81,56 +121,111 @@
|
||||
version = "17.5.0";
|
||||
sha256 = "00gz2i8kx4mlq1ywj3imvf7wc6qzh0bsnynhw06z0mgyha1a21jy";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
||||
version = "6.0.25";
|
||||
sha256 = "052388yjivzkfllkss0nljbzmjx787jqdjsbb6ls855sp6wh9xfd";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
||||
version = "8.0.0";
|
||||
sha256 = "0bpg3v9dnalz7yh7lsgriw9rnm9jx37mqhhvf7snznb3sfk7rgwb";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "103xy6kncjwbbchfnpqvsjpjy92x3dralcg9pw939jp0dwggwarz";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
||||
version = "8.0.0";
|
||||
sha256 = "1c7l68bm05d94x5wk1y33mnd4v8m196vyprgrzqnh94yrqy6fkf7";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
||||
version = "6.0.25";
|
||||
sha256 = "13m14pdx5xfxky07xgxf6hjd7g9l4k6k40wvp9znhvn27pa0wdxv";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
||||
version = "8.0.0";
|
||||
sha256 = "1hdv825s964vfcgnk94pzhgxnj948f1vdj423jjxpkppcy30fl0m";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "132pgjhv42mqzx4007sd59bkds0fwsv5xaz07y2yffbn3lzr228k";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
||||
version = "8.0.0";
|
||||
sha256 = "0jmzf58vv45j0hqlxq8yalpjwi328vp2mjr3h0pdg0qr143iivnr";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.win-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "039433rm4w37h9qri11v3lrpddpz7zcly9kq8vmk6w1ixzlqwf01";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.win-x64";
|
||||
version = "8.0.0";
|
||||
sha256 = "1n8yr13df2f6jhxpfazs6rxahfqm18fhjvfm16g5d60c3za1hwnk";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Ref";
|
||||
version = "6.0.25";
|
||||
sha256 = "0jfhmfxpx1h4f3axgf60gc8d4cnlvbb853400kag6nk0875hr0x1";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Ref";
|
||||
version = "8.0.0";
|
||||
sha256 = "0hyvbh86433764qqqhw9i7ga0ax7bbdmzh77jw58pq0ggm41cff9";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
||||
version = "6.0.25";
|
||||
sha256 = "0jpcmva1l8z36r4phz055l7fz9s6z8pv8pqc4ia69mhhgvr0ks7y";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
||||
version = "8.0.0";
|
||||
sha256 = "0gwqmkmr7jy3sjh9gha82amlry41gp8nwswy2iqfw54f28db63n7";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "012jml0bqxbspahf1j4bvvd91pz85hsbcyhq00gxczcazhxpkhz4";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
||||
version = "8.0.0";
|
||||
sha256 = "042cjvnwrrjs3mw5q8q5kinh0cwkks33i3n1vyifaid2jbr3wlc0";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
||||
version = "6.0.25";
|
||||
sha256 = "0wgwxpyy1n550sw7npjg69zpxknwn0ay30m2qybvqb5mj857qzxi";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
||||
version = "8.0.0";
|
||||
sha256 = "06ndp4wh1cap01dql3nixka4g56bf6ipmqys7xaxvg4xisf79x8d";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "08vr7c5bg5x3w35l54z1azif7ysfc2yiyz50ip1dl0mpqywvlswr";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
||||
version = "8.0.0";
|
||||
sha256 = "1kh5bnaf6h9mr4swcalrp304625frjiw6mlz1052rxwzsdq98a96";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.win-x64";
|
||||
version = "6.0.25";
|
||||
sha256 = "03snpmx204xvc9668riisvvdjjgdqhwj7yjp85w5lh8j8ygrqkif";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.win-x64";
|
||||
version = "8.0.0";
|
||||
@@ -201,15 +296,20 @@
|
||||
version = "13.0.1";
|
||||
sha256 = "0fijg0w6iwap8gvzyjnndds0q4b8anwxxvik7y8vgq97dram4srb";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Newtonsoft.Json";
|
||||
version = "13.0.3";
|
||||
sha256 = "0xrwysmrn4midrjal8g2hr1bbg38iyisl0svamb11arqws4w2bw7";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Common";
|
||||
version = "6.5.0";
|
||||
sha256 = "1k24azm8hvsm74fmy67i1a3jkzpnsa9hp6dzbam8cdz8ayy6zqc8";
|
||||
version = "6.8.0";
|
||||
sha256 = "0l3ij8iwy7wj6s7f93lzi9168r4wz8zyin6a08iwgk7hvq44cia1";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Configuration";
|
||||
version = "6.5.0";
|
||||
sha256 = "1yakqg4x5j69p5zi5wz77ybgyrblrnszj3z1ddsi1ahkxpffx2w4";
|
||||
version = "6.8.0";
|
||||
sha256 = "0x03p408smkmv1gv7pmvsia4lkn0xaj4wfrkl58pjf8bbv51y0yw";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Frameworks";
|
||||
@@ -218,28 +318,28 @@
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Frameworks";
|
||||
version = "6.5.0";
|
||||
sha256 = "0s37d1p4md0k6d4cy6sq36f2dgkd9qfbzapxhkvi8awwh0vrynhj";
|
||||
version = "6.8.0";
|
||||
sha256 = "0i2xvhgkjkjr496i3pg8hamwv6505fia45qhn7jg5m01wb3cvsjl";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Packaging";
|
||||
version = "6.5.0";
|
||||
sha256 = "0rkczrmw7rss91nam10rf771r31k3fwc271nvh0wn35axv3ibssl";
|
||||
version = "6.8.0";
|
||||
sha256 = "031z4s905bxi94h3f0qy4j1b6jxdxgqgpkzqvvpfxch07szxcbim";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Protocol";
|
||||
version = "6.5.0";
|
||||
sha256 = "16df7p835aqach4qhnp9dwa335hgfjmmj520fy0h8in1zrnlfazh";
|
||||
version = "6.7.0";
|
||||
sha256 = "1v5ibnq2mp801vw68zyj169hkj3xm7h55824i33n1jxxj2vs3vbk";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Versioning";
|
||||
version = "6.5.0";
|
||||
sha256 = "095al1ys6379gl52b6fvcn7pplc8gvbphsjz28124kcbx1a5g6vs";
|
||||
version = "6.8.0";
|
||||
sha256 = "1sd25h46fd12ng780r02q4ijcx1imkb53kj1y2y7cwg5myh537ks";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NUnit";
|
||||
version = "3.13.3";
|
||||
sha256 = "0wdzfkygqnr73s6lpxg5b1pwaqz9f414fxpvpdmf72bvh4jaqzv6";
|
||||
version = "3.14.0";
|
||||
sha256 = "19p8911lrfds1k9rv47jk1bbn665s0pvghkd06gzbg78j6mzzqqa";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NUnit.Analyzers";
|
||||
@@ -273,8 +373,8 @@
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Formats.Asn1";
|
||||
version = "5.0.0";
|
||||
sha256 = "1axc8z0839yvqi2cb63l73l6d9j6wd20lsbdymwddz9hvrsgfwpn";
|
||||
version = "6.0.0";
|
||||
sha256 = "1vvr7hs4qzjqb37r0w1mxq7xql2b17la63jwvmgv65s1hj00g8r9";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.IO.Abstractions";
|
||||
@@ -316,15 +416,10 @@
|
||||
version = "4.5.0";
|
||||
sha256 = "1wvwanz33fzzbnd2jalar0p0z3x0ba53vzx1kazlskp7pwyhlnq0";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Cryptography.Cng";
|
||||
version = "5.0.0";
|
||||
sha256 = "06hkx2za8jifpslkh491dfwzm5dxrsyxzj5lsc0achb6yzg4zqlw";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Cryptography.Pkcs";
|
||||
version = "5.0.0";
|
||||
sha256 = "0hb2mndac3xrw3786bsjxjfh19bwnr991qib54k6wsqjhjyyvbwj";
|
||||
version = "6.0.4";
|
||||
sha256 = "0hh5h38pnxmlrnvs72f2hzzpz4b2caiiv6xf8y7fzdg84r3imvfr";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Cryptography.ProtectedData";
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
dotnet \
|
||||
"/Users/patrick/.nuget/packages/myriad.sdk/0.8.3/build/../tools/net6.0/any/Myriad.dll" \
|
||||
--inputfile "/Users/patrick/Documents/GitHub/MyriadPlugin/UsePlugin/RecordFile.fs" \
|
||||
--outputfile "/Users/patrick/Documents/GitHub/MyriadPlugin/UsePlugin/Generated.fs" \
|
||||
--configfile "/Users/patrick/Documents/GitHub/MyriadPlugin/UsePlugin/myriad.toml" \
|
||||
--contextfile "/Users/patrick/Documents/GitHub/MyriadPlugin/UsePlugin/obj/myriad.context.toml" \
|
||||
--inputfile "/Users/patrick/Documents/GitHub/MyriadPlugin/ConsumePlugin/RecordFile.fs" \
|
||||
--outputfile "/Users/patrick/Documents/GitHub/MyriadPlugin/ConsumePlugin/Generated.fs" \
|
||||
--configfile "/Users/patrick/Documents/GitHub/MyriadPlugin/ConsumePlugin/myriad.toml" \
|
||||
--contextfile "/Users/patrick/Documents/GitHub/MyriadPlugin/ConsumePlugin/obj/myriad.context.toml" \
|
||||
--plugin "/Users/patrick/Documents/GitHub/MyriadPlugin/MyriadPlugin/bin/Debug/net8.0/MyriadPlugin.dll"
|
||||
|
Reference in New Issue
Block a user