Compare commits

..

2 Commits

Author SHA1 Message Date
Smaug123
d86bd743af Demonstrate that this is too dumb 2024-02-18 18:37:26 +00:00
Smaug123
dff2431bc8 First pass at handling generics in cata 2024-02-18 18:33:23 +00:00
32 changed files with 222 additions and 873 deletions

View File

@@ -3,16 +3,16 @@
"isRoot": true, "isRoot": true,
"tools": { "tools": {
"fantomas": { "fantomas": {
"version": "6.3.4", "version": "6.3.0-alpha-007",
"commands": [ "commands": [
"fantomas" "fantomas"
] ]
}, },
"fsharp-analyzers": { "fsharp-analyzers": {
"version": "0.25.0", "version": "0.24.0",
"commands": [ "commands": [
"fsharp-analyzers" "fsharp-analyzers"
] ]
} }
} }
} }

View File

@@ -2,6 +2,7 @@ root=true
[*] [*]
charset=utf-8 charset=utf-8
end_of_line=crlf
trim_trailing_whitespace=true trim_trailing_whitespace=true
insert_final_newline=true insert_final_newline=true
indent_style=space indent_style=space

10
.gitattributes vendored
View File

@@ -1,5 +1,5 @@
* eol=auto * eol=auto
*.sh text eol=lf *.sh text eol=lf
*.yaml text *.yaml text
*.nix text eol=lf *.nix text eol=lf
hooks/pre-push text eol=lf hooks/pre-push text eol=lf

View File

@@ -28,7 +28,7 @@ jobs:
with: with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -49,7 +49,7 @@ jobs:
with: with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -58,7 +58,7 @@ jobs:
- name: Build project - name: Build project
run: nix develop --command dotnet build ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj run: nix develop --command dotnet build ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj
- name: Run analyzers - name: Run analyzers
run: nix run .#fsharp-analyzers -- --project ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj --analyzers-path ./.analyzerpackages/g-research.fsharp.analyzers/*/ --verbosity detailed --report ./analysis.sarif --treat-as-error GRA-STRING-001 GRA-STRING-002 GRA-STRING-003 GRA-UNIONCASE-001 GRA-INTERPOLATED-001 GRA-TYPE-ANNOTATE-001 GRA-VIRTUALCALL-001 GRA-IMMUTABLECOLLECTIONEQUALITY-001 GRA-JSONOPTS-001 GRA-LOGARGFUNCFULLAPP-001 GRA-DISPBEFOREASYNC-001 --exclude-analyzers PartialAppAnalyzer run: nix run .#fsharp-analyzers -- --project ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj --analyzers-path ./.analyzerpackages/g-research.fsharp.analyzers/0.8.0/ --verbosity detailed --report ./analysis.sarif --treat-as-error GRA-STRING-001 GRA-STRING-002 GRA-STRING-003 GRA-UNIONCASE-001 GRA-INTERPOLATED-001 GRA-TYPE-ANNOTATE-001 GRA-VIRTUALCALL-001 GRA-IMMUTABLECOLLECTIONEQUALITY-001 GRA-JSONOPTS-001 GRA-LOGARGFUNCFULLAPP-001 GRA-DISPBEFOREASYNC-001 --exclude-analyzers PartialAppAnalyzer
build-nix: build-nix:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -66,7 +66,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -79,7 +79,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -92,7 +92,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -105,7 +105,7 @@ jobs:
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -118,7 +118,7 @@ jobs:
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -132,7 +132,7 @@ jobs:
with: with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -188,7 +188,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@V27 uses: cachix/install-nix-action@v25
with: with:
extra_nix_config: | extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -206,25 +206,3 @@ jobs:
path: packed-attribute path: packed-attribute
- name: Publish to NuGet (attribute) - name: Publish to NuGet (attribute)
run: nix develop --command dotnet nuget push "packed-attribute/WoofWare.Myriad.Plugins.Attributes.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate run: nix develop --command dotnet nuget push "packed-attribute/WoofWare.Myriad.Plugins.Attributes.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
github-release-plugin:
runs-on: ubuntu-latest
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
needs: [all-required-checks-complete]
environment: main-deploy
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Download NuGet artifact (plugin)
uses: actions/download-artifact@v4
with:
name: nuget-package-plugin
- name: Download NuGet artifact (attribute)
uses: actions/download-artifact@v4
with:
name: nuget-package-attribute
- name: Tag and release plugin
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: sh .github/workflows/tag.sh

View File

@@ -1,17 +0,0 @@
#!/bin/sh
find . -maxdepth 1 -type f -name '*.nupkg' -exec sh -c 'tag=$(basename "$1" .nupkg); git tag "$tag"; git push origin "$tag"' shell {} \;
export TAG
TAG=$(find . -maxdepth 1 -type f -name 'WoofWare.Myriad.Plugins.*.nupkg' -exec sh -c 'basename "$1" .nupkg' shell {} \; | grep -v Attributes)
case "$TAG" in
*"
"*)
echo "Error: TAG contains a newline; multiple plugins found."
exit 1
;;
esac
# target_commitish empty indicates the repo default branch
curl -L -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/Smaug123/WoofWare.Myriad/releases -d '{"tag_name":"'"$TAG"'","target_commitish":"","name":"'"$TAG"'","draft":false,"prerelease":false,"generate_release_notes":false}'

View File

@@ -11,12 +11,12 @@ type PairOpKind =
| ThenDoSeq | ThenDoSeq
[<CreateCatamorphism "TreeCata">] [<CreateCatamorphism "TreeCata">]
type Tree<'a, 'b> = type Tree<'a> =
| Const of Const<'a> * 'b | Const of Const<'a>
| Pair of Tree<'a, 'b> * Tree<'a, 'b> * PairOpKind | Pair of Tree<'a> * Tree<'a> * PairOpKind
| Sequential of Tree<'a, 'b> list | Sequential of Tree<'a> list
| Builder of Tree<'a, 'b> * TreeBuilder<'b, 'a> | Builder of Tree<'a> * TreeBuilder<'a>
and TreeBuilder<'b, 'a> = and TreeBuilder<'a> =
| Child of TreeBuilder<'b, 'a> | Child of TreeBuilder<'a>
| Parent of Tree<'a, 'b> | Parent of Tree<'a>

View File

@@ -12,16 +12,16 @@ namespace ConsumePlugin
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Description of how to combine cases during a fold /// Description of how to combine cases during a fold
type TreeBuilderCataCase<'b, 'a, 'TreeBuilder, 'Tree> = type TreeBuilderCataCase<'a, 'TreeBuilder, 'Tree> =
/// How to operate on the Child case /// How to operate on the Child case
abstract Child : 'TreeBuilder -> 'TreeBuilder abstract Child : 'TreeBuilder -> 'TreeBuilder
/// How to operate on the Parent case /// How to operate on the Parent case
abstract Parent : 'Tree -> 'TreeBuilder abstract Parent : 'Tree -> 'TreeBuilder
/// Description of how to combine cases during a fold /// Description of how to combine cases during a fold
type TreeCataCase<'a, 'b, 'TreeBuilder, 'Tree> = type TreeCataCase<'a, 'TreeBuilder, 'Tree> =
/// How to operate on the Const case /// How to operate on the Const case
abstract Const : Const<'a> -> 'b -> 'Tree abstract Const : Const -> 'Tree
/// How to operate on the Pair case /// How to operate on the Pair case
abstract Pair : 'Tree -> 'Tree -> PairOpKind -> 'Tree abstract Pair : 'Tree -> 'Tree -> PairOpKind -> 'Tree
/// How to operate on the Sequential case /// How to operate on the Sequential case
@@ -30,30 +30,30 @@ type TreeCataCase<'a, 'b, 'TreeBuilder, 'Tree> =
abstract Builder : 'Tree -> 'TreeBuilder -> 'Tree abstract Builder : 'Tree -> 'TreeBuilder -> 'Tree
/// Specifies how to perform a fold (catamorphism) over the type Tree and its friends. /// Specifies how to perform a fold (catamorphism) over the type Tree and its friends.
type TreeCata<'b, 'a, 'TreeBuilder, 'Tree> = type TreeCata<'a, 'a, 'TreeBuilder, 'Tree> =
{ {
/// How to perform a fold (catamorphism) over the type TreeBuilder /// How to perform a fold (catamorphism) over the type TreeBuilder
TreeBuilder : TreeBuilderCataCase<'b, 'a, 'TreeBuilder, 'Tree> TreeBuilder : TreeBuilderCataCase<'a, 'TreeBuilder, 'Tree>
/// How to perform a fold (catamorphism) over the type Tree /// How to perform a fold (catamorphism) over the type Tree
Tree : TreeCataCase<'a, 'b, 'TreeBuilder, 'Tree> Tree : TreeCataCase<'a, 'TreeBuilder, 'Tree>
} }
/// Methods to perform a catamorphism over the type Tree /// Methods to perform a catamorphism over the type Tree
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module TreeCata = module TreeCata =
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
type private Instruction<'b, 'a> = type private Instruction<'a, 'a> =
| Process__TreeBuilder of TreeBuilder<'b, 'a> | Process__TreeBuilder of TreeBuilder<'a>
| Process__Tree of Tree<'a, 'b> | Process__Tree of Tree<'a>
| TreeBuilder_Child | TreeBuilder_Child
| TreeBuilder_Parent | TreeBuilder_Parent
| Tree_Pair of PairOpKind | Tree_Pair of PairOpKind
| Tree_Sequential of int | Tree_Sequential of int
| Tree_Builder | Tree_Builder
let private loop (cata : TreeCata<'b, 'a, 'TreeBuilder, 'Tree>) (instructions : ResizeArray<Instruction<'b, 'a>>) = let private loop (cata : TreeCata<_, _, _, _>) (instructions : ResizeArray<Instruction<_, _>>) =
let treeStack = ResizeArray<'Tree> () let treeStack = ResizeArray ()
let treeBuilderStack = ResizeArray<'TreeBuilder> () let treeBuilderStack = ResizeArray ()
while instructions.Count > 0 do while instructions.Count > 0 do
let currentInstruction = instructions.[instructions.Count - 1] let currentInstruction = instructions.[instructions.Count - 1]
@@ -70,7 +70,7 @@ module TreeCata =
instructions.Add (Instruction.Process__Tree arg0_0) instructions.Add (Instruction.Process__Tree arg0_0)
| Instruction.Process__Tree x -> | Instruction.Process__Tree x ->
match x with match x with
| Tree.Const (arg0_0, arg1_0) -> cata.Tree.Const arg0_0 arg1_0 |> treeStack.Add | Tree.Const (arg0_0) -> cata.Tree.Const arg0_0 |> treeStack.Add
| Tree.Pair (arg0_0, arg1_0, arg2_0) -> | Tree.Pair (arg0_0, arg1_0, arg2_0) ->
instructions.Add (Instruction.Tree_Pair (arg2_0)) instructions.Add (Instruction.Tree_Pair (arg2_0))
instructions.Add (Instruction.Process__Tree arg0_0) instructions.Add (Instruction.Process__Tree arg0_0)
@@ -121,8 +121,8 @@ module TreeCata =
/// Execute the catamorphism. /// Execute the catamorphism.
let runTreeBuilder let runTreeBuilder
(cata : TreeCata<'b, 'a, 'TreeBuilderRet, 'TreeRet>) (cata : TreeCata<'a, 'a, 'TreeBuilderRet, 'TreeRet>)
(x : TreeBuilder<'b, 'a>) (x : TreeBuilder<'a, 'a>)
: 'TreeBuilderRet : 'TreeBuilderRet
= =
let instructions = ResizeArray () let instructions = ResizeArray ()
@@ -131,7 +131,7 @@ module TreeCata =
Seq.exactlyOne treeBuilderRetStack Seq.exactlyOne treeBuilderRetStack
/// Execute the catamorphism. /// Execute the catamorphism.
let runTree (cata : TreeCata<'b, 'a, 'TreeBuilderRet, 'TreeRet>) (x : Tree<'a, 'b>) : 'TreeRet = let runTree (cata : TreeCata<'a, 'a, 'TreeBuilderRet, 'TreeRet>) (x : Tree<'a, 'a>) : 'TreeRet =
let instructions = ResizeArray () let instructions = ResizeArray ()
instructions.Add (Instruction.Process__Tree x) instructions.Add (Instruction.Process__Tree x)
let treeBuilderRetStack, treeRetStack = loop cata instructions let treeBuilderRetStack, treeRetStack = loop cata instructions

View File

@@ -33,8 +33,8 @@ module FileSystemItemCata =
| Process__FileSystemItem of FileSystemItem | Process__FileSystemItem of FileSystemItem
| FileSystemItem_Directory of string * int * int | FileSystemItem_Directory of string * int * int
let private loop (cata : FileSystemCata<'FileSystemItem>) (instructions : ResizeArray<Instruction>) = let private loop (cata : FileSystemCata<_>) (instructions : ResizeArray<Instruction>) =
let fileSystemItemStack = ResizeArray<'FileSystemItem> () let fileSystemItemStack = ResizeArray ()
while instructions.Count > 0 do while instructions.Count > 0 do
let currentInstruction = instructions.[instructions.Count - 1] let currentInstruction = instructions.[instructions.Count - 1]
@@ -108,8 +108,8 @@ module GiftCata =
| Gift_Boxed | Gift_Boxed
| Gift_WithACard of string | Gift_WithACard of string
let private loop (cata : GiftCata<'Gift>) (instructions : ResizeArray<Instruction>) = let private loop (cata : GiftCata<_>) (instructions : ResizeArray<Instruction>) =
let giftStack = ResizeArray<'Gift> () let giftStack = ResizeArray ()
while instructions.Count > 0 do while instructions.Count > 0 do
let currentInstruction = instructions.[instructions.Count - 1] let currentInstruction = instructions.[instructions.Count - 1]

View File

@@ -5,7 +5,6 @@
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Mock record type for an interface /// Mock record type for an interface
@@ -26,11 +25,10 @@ type internal PublicTypeMock =
interface IPublicType with interface IPublicType with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0)
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1) member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1)
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Mock record type for an interface /// Mock record type for an interface
@@ -51,11 +49,10 @@ type public PublicTypeInternalFalseMock =
interface IPublicTypeInternalFalse with interface IPublicTypeInternalFalse with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0)
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1) member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1)
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Mock record type for an interface /// Mock record type for an interface
@@ -74,10 +71,9 @@ type internal InternalTypeMock =
interface InternalType with interface InternalType with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0)
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Mock record type for an interface /// Mock record type for an interface
@@ -96,10 +92,9 @@ type private PrivateTypeMock =
interface PrivateType with interface PrivateType with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0)
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Mock record type for an interface /// Mock record type for an interface
@@ -118,10 +113,9 @@ type private PrivateTypeInternalFalseMock =
interface PrivateTypeInternalFalse with interface PrivateTypeInternalFalse with
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0)
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Mock record type for an interface /// Mock record type for an interface
@@ -137,10 +131,9 @@ type internal VeryPublicTypeMock<'a, 'b> =
} }
interface VeryPublicType<'a, 'b> with interface VeryPublicType<'a, 'b> with
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0) member this.Mem1 (arg_0_0) = this.Mem1 (arg_0_0)
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
/// Mock record type for an interface /// Mock record type for an interface
@@ -166,9 +159,9 @@ type internal CurriedMock<'a> =
} }
interface Curried<'a> with interface Curried<'a> with
member this.Mem1 arg_0_0 arg_1_0 = this.Mem1 (arg_0_0) (arg_1_0) member this.Mem1 (arg_0_0) (arg_1_0) = this.Mem1 (arg_0_0) (arg_1_0)
member this.Mem2 (arg_0_0, arg_0_1) arg_1_0 = this.Mem2 (arg_0_0, arg_0_1) (arg_1_0) member this.Mem2 (arg_0_0, arg_0_1) (arg_1_0) = this.Mem2 (arg_0_0, arg_0_1) (arg_1_0)
member this.Mem3 ((arg_0_0, arg_0_1)) arg_1_0 = this.Mem3 (arg_0_0, arg_0_1) (arg_1_0) member this.Mem3 ((arg_0_0, arg_0_1)) (arg_1_0) = this.Mem3 (arg_0_0, arg_0_1) (arg_1_0)
member this.Mem4 ((arg_0_0, arg_0_1)) ((arg_1_0, arg_1_1)) = member this.Mem4 ((arg_0_0, arg_0_1)) ((arg_1_0, arg_1_1)) =
this.Mem4 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) this.Mem4 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
@@ -178,31 +171,3 @@ type internal CurriedMock<'a> =
member this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) = member this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) =
this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1)
namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins
/// Mock record type for an interface
type internal TypeWithInterfaceMock =
{
/// Implementation of IDisposable.Dispose
Dispose : unit -> unit
Mem1 : string option -> string[] Async
Mem2 : unit -> string[] Async
}
/// An implementation where every method throws.
static member Empty : TypeWithInterfaceMock =
{
Dispose = (fun _ -> ())
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
}
interface TypeWithInterface with
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
member this.Mem2 () = this.Mem2 (())
interface System.IDisposable with
member this.Dispose () : unit = this.Dispose ()

View File

@@ -288,52 +288,7 @@ module PureGymApi =
| v -> v), | v -> v),
System.Uri ( System.Uri (
("/v2/gymSessions/member" ("/v2/gymSessions/member"
+ (if "/v2/gymSessions/member".IndexOf (char 63) > 0 then + "?fromDate="
"&"
else
"?")
+ "fromDate="
+ ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)
+ "&toDate="
+ ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)),
System.UriKind.Relative
)
)
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = uri
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
let! jsonNode =
System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct)
|> Async.AwaitTask
return Sessions.jsonParse jsonNode
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetSessionsWithQuery (fromDate : DateOnly, toDate : DateOnly, ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let uri =
System.Uri (
(match client.BaseAddress with
| null -> System.Uri "https://whatnot.com"
| v -> v),
System.Uri (
("/v2/gymSessions/member?foo=1"
+ (if "/v2/gymSessions/member?foo=1".IndexOf (char 63) > 0 then
"&"
else
"?")
+ "fromDate="
+ ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode) + ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)
+ "&toDate=" + "&toDate="
+ ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)), + ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)),
@@ -1185,69 +1140,6 @@ module ApiWithHeaders =
member _.SomeHeader : string = someHeader () member _.SomeHeader : string = someHeader ()
member _.SomeOtherHeader : int = someOtherHeader () member _.SomeOtherHeader : int = someOtherHeader ()
member this.GetPathParam (parameter : string, ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let uri =
System.Uri (
(match client.BaseAddress with
| null ->
raise (
System.ArgumentNullException (
nameof (client.BaseAddress),
"No base address was supplied on the type, and no BaseAddress was on the HttpClient."
)
)
| v -> v),
System.Uri (
"endpoint/{param}"
.Replace ("{param}", parameter.ToString () |> System.Web.HttpUtility.UrlEncode),
System.UriKind.Relative
)
)
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = uri
)
do httpMessage.Headers.Add ("X-Foo", this.SomeHeader.ToString ())
do httpMessage.Headers.Add ("Authorization", this.SomeOtherHeader.ToString ())
do httpMessage.Headers.Add ("Header-Name", "Header-Value")
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! responseString = response.Content.ReadAsStringAsync ct |> Async.AwaitTask
return responseString
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
}
namespace PureGym
open System
open System.Threading
open System.Threading.Tasks
open System.IO
open System.Net
open System.Net.Http
open RestEase
/// Module for constructing a REST client.
[<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
(someHeader : unit -> string)
(someOtherHeader : unit -> int)
(client : System.Net.Http.HttpClient)
: IApiWithHeaders2
=
{ new IApiWithHeaders2 with
member _.SomeHeader : string = someHeader ()
member _.SomeOtherHeader : int = someOtherHeader ()
member this.GetPathParam (parameter : string, ct : CancellationToken option) = member this.GetPathParam (parameter : string, ct : CancellationToken option) =
async { async {
let! ct = Async.CancellationToken let! ct = Async.CancellationToken

View File

@@ -33,8 +33,8 @@ module MyListCata =
| Process__MyList of MyList<'a> | Process__MyList of MyList<'a>
| MyList_Cons of 'a | MyList_Cons of 'a
let private loop (cata : MyListCata<'a, 'MyList>) (instructions : ResizeArray<Instruction<'a>>) = let private loop (cata : MyListCata<_, _>) (instructions : ResizeArray<Instruction<_>>) =
let myListStack = ResizeArray<'MyList> () let myListStack = ResizeArray ()
while instructions.Count > 0 do while instructions.Count > 0 do
let currentInstruction = instructions.[instructions.Count - 1] let currentInstruction = instructions.[instructions.Count - 1]
@@ -89,8 +89,8 @@ module MyList2Cata =
| Process__MyList2 of MyList2<'a> | Process__MyList2 of MyList2<'a>
| MyList2_Cons of 'a | MyList2_Cons of 'a
let private loop (cata : MyList2Cata<'a, 'MyList2>) (instructions : ResizeArray<Instruction<'a>>) = let private loop (cata : MyList2Cata<_, _>) (instructions : ResizeArray<Instruction<_>>) =
let myList2Stack = ResizeArray<'MyList2> () let myList2Stack = ResizeArray ()
while instructions.Count > 0 do while instructions.Count > 0 do
let currentInstruction = instructions.[instructions.Count - 1] let currentInstruction = instructions.[instructions.Count - 1]

View File

@@ -1,6 +1,5 @@
namespace SomeNamespace namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins open WoofWare.Myriad.Plugins
[<GenerateMock>] [<GenerateMock>]
@@ -42,9 +41,3 @@ type Curried<'a> =
abstract Mem4 : (int * string) -> ('a * int) -> string abstract Mem4 : (int * string) -> ('a * int) -> string
abstract Mem5 : x : int * string -> ('a * int) -> string abstract Mem5 : x : int * string -> ('a * int) -> string
abstract Mem6 : int * string -> y : 'a * int -> string abstract Mem6 : int * string -> y : 'a * int -> string
[<GenerateMock>]
type TypeWithInterface =
inherit IDisposable
abstract Mem1 : string option -> string[] Async
abstract Mem2 : unit -> string[] Async

View File

@@ -38,10 +38,6 @@ type IPureGymApi =
abstract GetSessions : abstract GetSessions :
[<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions> [<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions>
[<Get "/v2/gymSessions/member?foo=1">]
abstract GetSessionsWithQuery :
[<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions>
// An example from RestEase's own docs // An example from RestEase's own docs
[<Post "users/new">] [<Post "users/new">]
abstract CreateUserString : [<Body>] user : string * ?ct : CancellationToken -> Task<string> abstract CreateUserString : [<Body>] user : string * ?ct : CancellationToken -> Task<string>
@@ -124,8 +120,7 @@ type internal IApiWithoutBaseAddress =
[<WoofWare.Myriad.Plugins.HttpClient>] [<WoofWare.Myriad.Plugins.HttpClient>]
[<BasePath "foo">] [<BasePath "foo">]
type IApiWithBasePath = type IApiWithBasePath =
// Example where we use the bundled attributes rather than RestEase's [<Get "endpoint/{param}">]
[<WoofWare.Myriad.Plugins.RestEase.Get "endpoint/{param}">]
abstract GetPathParam : [<Path "param">] parameter : string * ?cancellationToken : CancellationToken -> Task<string> abstract GetPathParam : [<Path "param">] parameter : string * ?cancellationToken : CancellationToken -> Task<string>
[<WoofWare.Myriad.Plugins.HttpClient>] [<WoofWare.Myriad.Plugins.HttpClient>]
@@ -146,16 +141,3 @@ type IApiWithHeaders =
[<Get "endpoint/{param}">] [<Get "endpoint/{param}">]
abstract GetPathParam : [<Path "param">] parameter : string * ?ct : CancellationToken -> Task<string> abstract GetPathParam : [<Path "param">] parameter : string * ?ct : CancellationToken -> Task<string>
[<WoofWare.Myriad.Plugins.HttpClient>]
[<WoofWare.Myriad.Plugins.RestEase.Header("Header-Name", "Header-Value")>]
type IApiWithHeaders2 =
[<WoofWare.Myriad.Plugins.RestEase.Header "X-Foo">]
abstract SomeHeader : string
[<WoofWare.Myriad.Plugins.RestEase.Header "Authorization">]
abstract SomeOtherHeader : int
[<Get "endpoint/{param}">]
abstract GetPathParam :
[<WoofWare.Myriad.Plugins.RestEase.Path "param">] parameter : string * ?ct : CancellationToken -> Task<string>

View File

@@ -332,7 +332,7 @@ thereby allowing the programmer to use F#'s record-update syntax.
Takes a collection of mutually recursive discriminated unions: Takes a collection of mutually recursive discriminated unions:
```fsharp ```fsharp
[<CreateCatamorphism "MyCata">] [<CreateCatamorphism>]
type Expr = type Expr =
| Const of Const | Const of Const
| Pair of Expr * Expr * PairOpKind | Pair of Expr * Expr * PairOpKind
@@ -356,7 +356,7 @@ type ExprBuilderCata<'Expr, 'ExprBuilder> =
abstract Child : 'ExprBuilder -> 'ExprBuilder abstract Child : 'ExprBuilder -> 'ExprBuilder
abstract Parent : 'Expr -> 'ExprBuilder abstract Parent : 'Expr -> 'ExprBuilder
type MyCata<'Expr, 'ExprBuilder> = type Cata<'Expr, 'ExprBuilder> =
{ {
Expr : ExprCata<'Expr, 'ExprBuilder> Expr : ExprCata<'Expr, 'ExprBuilder>
ExprBuilder : ExprBuilderCata<'Expr, 'ExprBuilder> ExprBuilder : ExprBuilderCata<'Expr, 'ExprBuilder>
@@ -364,10 +364,10 @@ type MyCata<'Expr, 'ExprBuilder> =
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module ExprCata = module ExprCata =
let runExpr (cata : MyCata<'ExprRet, 'ExprBuilderRet>) (x : Expr) : 'ExprRet = let runExpr (cata : Cata<'ExprRet, 'ExprBuilderRet>) (x : Expr) : 'ExprRet =
failwith "this is implemented" failwith "this is implemented"
let runExprBuilder (cata : MyCata<'ExprRet, 'ExprBuilderRet>) (x : ExprBuilder) : 'ExprBuilderRet = let runExprBuilder (cata : Cata<'ExprRet, 'ExprBuilderRet>) (x : ExprBuilder) : 'ExprBuilderRet =
failwith "this is implemented" failwith "this is implemented"
``` ```
@@ -381,10 +381,6 @@ and then each time you only plug in what you want to do.
* Mutually recursive DUs are supported (as in the example above). * Mutually recursive DUs are supported (as in the example above).
Every DU in a recursive `type Foo... and Bar...` knot will be given an appropriate cata, as long as any one of those DUs has the `[<CreateCatamorphism>]` attribute. Every DU in a recursive `type Foo... and Bar...` knot will be given an appropriate cata, as long as any one of those DUs has the `[<CreateCatamorphism>]` attribute.
* There is *limited* support for records and for lists. * There is *limited* support for records and for lists.
* There is *extremely brittle* support for generics in the DUs you are cata'ing over.
It is based on the names of the generic parameters, so you must ensure that generic parameters with the same name have the same meaning across the various cases in your recursive knot of DUs.
(If you overstep the bounds of what this generator can do, you will get compile-time errors, e.g. with generics being constrained to each other's values.)
See the [List tests](./WoofWare.Myriad.Plugins.Test/TestCataGenerator/TestMyList2.fs) for an example, where we re-implement `FSharpList<'a>`.
### Limitations ### Limitations

View File

@@ -1,63 +0,0 @@
namespace WoofWare.Myriad.Plugins
open System
/// Module containing duplicates of the supported RestEase attributes, in case you don't want
/// to take a dependency on RestEase.
[<RequireQualifiedAccess>]
module RestEase =
/// Indicates that a method represents an HTTP Get query to the specified endpoint.
type GetAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Post query to the specified endpoint.
type PostAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Delete query to the specified endpoint.
type DeleteAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Head query to the specified endpoint.
type HeadAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Options query to the specified endpoint.
type OptionsAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Put query to the specified endpoint.
type PutAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Patch query to the specified endpoint.
type PatchAttribute (path : string) =
inherit Attribute ()
/// Indicates that a method represents an HTTP Trace query to the specified endpoint.
type TraceAttribute (path : string) =
inherit Attribute ()
/// Indicates that this argument to a method is interpolated into the HTTP request at runtime
/// by setting a query parameter (with the given name) to the value of the annotated argument.
type QueryAttribute (paramName : string) =
inherit Attribute ()
/// Indicates that this interface represents a REST client which accesses an API whose paths are
/// all relative to the given address.
type BaseAddressAttribute (addr : string) =
inherit Attribute ()
/// Indicates that this interface member causes the interface to set a header with the given name,
/// whose value is obtained whenever required by a fresh call to the interface member.
type HeaderAttribute (header : string, value : string option) =
inherit Attribute ()
new (header : string) = HeaderAttribute (header, None)
new (header : string, value : string) = HeaderAttribute (header, Some value)
/// Indicates that this argument to a method is interpolated into the request path at runtime
/// by writing it into the templated string that specifies the HTTP query e.g. in the `[<Get "/foo/{template}">]`.
type PathAttribute (path : string option) =
inherit Attribute ()
new (path : string) = PathAttribute (Some path)
new () = PathAttribute None

View File

@@ -18,33 +18,4 @@ WoofWare.Myriad.Plugins.JsonSerializeAttribute..ctor [constructor]: unit
WoofWare.Myriad.Plugins.JsonSerializeAttribute.DefaultIsExtensionMethod [static property]: [read-only] bool WoofWare.Myriad.Plugins.JsonSerializeAttribute.DefaultIsExtensionMethod [static property]: [read-only] bool
WoofWare.Myriad.Plugins.JsonSerializeAttribute.get_DefaultIsExtensionMethod [static method]: unit -> bool WoofWare.Myriad.Plugins.JsonSerializeAttribute.get_DefaultIsExtensionMethod [static method]: unit -> bool
WoofWare.Myriad.Plugins.RemoveOptionsAttribute inherit System.Attribute WoofWare.Myriad.Plugins.RemoveOptionsAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RemoveOptionsAttribute..ctor [constructor]: unit WoofWare.Myriad.Plugins.RemoveOptionsAttribute..ctor [constructor]: unit
WoofWare.Myriad.Plugins.RestEase inherit obj
WoofWare.Myriad.Plugins.RestEase+BaseAddressAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+BaseAddressAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+DeleteAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+DeleteAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+GetAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+GetAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+HeadAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+HeadAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: (string, string option)
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: (string, string)
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+OptionsAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+OptionsAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+PatchAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+PatchAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+PathAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: string option
WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: unit
WoofWare.Myriad.Plugins.RestEase+PostAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+PostAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+PutAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+PutAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+QueryAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+QueryAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+TraceAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+TraceAttribute..ctor [constructor]: string

View File

@@ -11,9 +11,11 @@ module TestSurface =
[<Test>] [<Test>]
let ``Ensure API surface has not been modified`` () = ApiSurface.assertIdentical assembly let ``Ensure API surface has not been modified`` () = ApiSurface.assertIdentical assembly
(*
[<Test>] [<Test>]
let ``Check version against remote`` () = let ``Check version against remote`` () =
MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins.Attributes" MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins.Attributes"
*)
[<Test ; Explicit>] [<Test ; Explicit>]
let ``Update API surface`` () = let ``Update API surface`` () =

View File

@@ -12,9 +12,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ApiSurface" Version="4.0.39" /> <PackageReference Include="ApiSurface" Version="4.0.28" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/>
<PackageReference Include="NUnit" Version="4.1.0"/> <PackageReference Include="NUnit" Version="3.13.3"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
</ItemGroup> </ItemGroup>

View File

@@ -19,7 +19,6 @@
<ItemGroup> <ItemGroup>
<Compile Include="Attributes.fs"/> <Compile Include="Attributes.fs"/>
<Compile Include="RestEase.fs" />
<EmbeddedResource Include="version.json"/> <EmbeddedResource Include="version.json"/>
<EmbeddedResource Include="SurfaceBaseline.txt"/> <EmbeddedResource Include="SurfaceBaseline.txt"/>
<None Include="..\README.md"> <None Include="..\README.md">

View File

@@ -1,7 +1,7 @@
{ {
"version": "3.0", "version": "2.2",
"publicReleaseRefSpec": [ "publicReleaseRefSpec": [
"^refs/heads/main$" "^refs/heads/main$"
], ],
"pathFilters": null "pathFilters": null
} }

View File

@@ -8,17 +8,17 @@ open FsCheck
[<TestFixture>] [<TestFixture>]
module TestCataGenerator = module TestCataGenerator =
let idCata<'a, 'b> : TreeCata<'a, 'b, _, _> = let idCata : TreeCata<_, _> =
{ {
Tree = Tree =
{ new TreeCataCase<_, _, _, _> with { new TreeCataCase<_, _> with
member _.Const x y = Const (x, y) member _.Const x = Const x
member _.Pair x y z = Pair (x, y, z) member _.Pair x y z = Pair (x, y, z)
member _.Sequential xs = Sequential xs member _.Sequential xs = Sequential xs
member _.Builder x b = Builder (x, b) member _.Builder x b = Builder (x, b)
} }
TreeBuilder = TreeBuilder =
{ new TreeBuilderCataCase<_, _, _, _> with { new TreeBuilderCataCase<_, _> with
member _.Child x = Child x member _.Child x = Child x
member _.Parent x = Parent x member _.Parent x = Parent x
} }
@@ -27,7 +27,7 @@ module TestCataGenerator =
[<Test>] [<Test>]
let ``Example`` () = let ``Example`` () =
let x = let x =
Tree.Pair (Tree.Const (Const.Verbatim 0, "hi"), Tree.Const (Const.String "", "bye"), PairOpKind.ThenDoSeq) Tree.Pair (Tree.Const (Const.Int 0), Tree.Const (Const.String ""), PairOpKind.ThenDoSeq)
TreeCata.runTree idCata x |> shouldEqual x TreeCata.runTree idCata x |> shouldEqual x
@@ -36,7 +36,7 @@ module TestCataGenerator =
let ``Cata works`` () = let ``Cata works`` () =
let builderCases = ref 0 let builderCases = ref 0
let property (x : Tree<int, string>) = let property (x : Tree) =
match x with match x with
| Tree.Builder _ -> Interlocked.Increment builderCases |> ignore | Tree.Builder _ -> Interlocked.Increment builderCases |> ignore
| _ -> () | _ -> ()

View File

@@ -21,6 +21,7 @@ module TestMyList =
Tail = tail Tail = tail
} }
} }
} }
[<Test>] [<Test>]

View File

@@ -14,8 +14,9 @@ module TestMyList2 =
{ new MyList2CataCase<'a, _> with { new MyList2CataCase<'a, _> with
member _.Nil = MyList2.Nil member _.Nil = MyList2.Nil
member _.Cons (head : 'a) (tail : MyList2<'a>) = MyList2.Cons (head, tail) member _.Cons head tail = MyList2.Cons (head, tail)
} }
} }
[<Test>] [<Test>]

View File

@@ -234,33 +234,6 @@ module TestPureGymRestApi =
api.GetSessions(startDate, endDate).Result |> shouldEqual expected api.GetSessions(startDate, endDate).Result |> shouldEqual expected
[<TestCaseSource(nameof sessionsCases)>]
let ``Test GetSessionsWithQuery``
(baseUri : Uri, (startDate : DateOnly, (endDate : DateOnly, (json : string, expected : Sessions))))
=
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
async {
message.Method |> shouldEqual HttpMethod.Get
// This one is specified as being absolute, in its attribute on the IPureGymApi type
let expectedUri =
let fromDate = dateOnlyToString startDate
let toDate = dateOnlyToString endDate
$"https://example.com/v2/gymSessions/member?foo=1&fromDate=%s{fromDate}&toDate=%s{toDate}"
message.RequestUri.ToString () |> shouldEqual expectedUri
let content = new StringContent (json)
let resp = new HttpResponseMessage (HttpStatusCode.OK)
resp.Content <- content
return resp
}
use client = HttpClientMock.make baseUri proc
let api = PureGymApi.make client
api.GetSessionsWithQuery(startDate, endDate).Result |> shouldEqual expected
[<Test>] [<Test>]
let ``URI example`` () = let ``URI example`` () =
let proc (message : HttpRequestMessage) : HttpResponseMessage Async = let proc (message : HttpRequestMessage) : HttpResponseMessage Async =

View File

@@ -33,12 +33,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ApiSurface" Version="4.0.39"/> <PackageReference Include="ApiSurface" Version="4.0.28"/>
<PackageReference Include="FsCheck" Version="2.16.6"/> <PackageReference Include="FsCheck" Version="2.16.6"/>
<PackageReference Include="FsUnit" Version="6.0.0"/> <PackageReference Include="FsUnit" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="NUnit" Version="4.1.0"/> <PackageReference Include="NUnit" Version="4.0.1"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -54,7 +54,6 @@ type internal InterfaceType =
{ {
Attributes : SynAttribute list Attributes : SynAttribute list
Name : LongIdent Name : LongIdent
Inherits : SynType list
Members : MemberInfo list Members : MemberInfo list
Properties : PropertyInfo list Properties : PropertyInfo list
Generics : SynTyparDecls option Generics : SynTyparDecls option
@@ -77,9 +76,6 @@ type internal AdtNode =
{ {
Type : SynType Type : SynType
Name : Ident option Name : Ident option
/// An ordered list, so you can look up any given generic within `this.Type`
/// to discover what its index is in the parent DU which defined it.
GenericsOfParent : SynTyparDecl list
} }
/// A DU is a sum of products (e.g. `type Thing = Foo of a * b`); /// A DU is a sum of products (e.g. `type Thing = Foo of a * b`);
@@ -89,10 +85,6 @@ type internal AdtProduct =
{ {
Name : SynIdent Name : SynIdent
Fields : AdtNode list Fields : AdtNode list
/// This AdtProduct represents a product in which there might be
/// some bound type parameters. This field lists the bound
/// type parameters in the order they appeared on the parent type.
Generics : SynTyparDecl list
} }
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@@ -132,11 +124,6 @@ module internal AstHelper =
// TODO: consider Microsoft.FSharp.Option or whatever it is // TODO: consider Microsoft.FSharp.Option or whatever it is
| _ -> false | _ -> 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 = let isListIdent (ident : SynLongIdent) : bool =
match ident.LongIdent with match ident.LongIdent with
| [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true | [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true
@@ -348,18 +335,7 @@ module internal AstHelper =
} }
|> List.singleton |> List.singleton
} }
| arg -> | _ -> failwith $"Unrecognised args in interface method declaration: %+A{args}"
{
HasParen = false
Args =
{
Attributes = []
IsOptional = false
Id = None
Type = arg
}
|> List.singleton
}
|> fun ty -> |> fun ty ->
{ ty with { ty with
HasParen = ty.HasParen || hasParen HasParen = ty.HasParen || hasParen
@@ -403,26 +379,22 @@ module internal AstHelper =
let attrs = attrs |> List.collect (fun s -> s.Attributes) let attrs = attrs |> List.collect (fun s -> s.Attributes)
let members, inherits = let members, properties =
match synTypeDefnRepr with match synTypeDefnRepr with
| SynTypeDefnRepr.ObjectModel (_kind, members, _) -> | SynTypeDefnRepr.ObjectModel (_kind, members, _) ->
members members
|> List.map (fun defn -> |> List.map (fun defn ->
match defn with match defn with
| SynMemberDefn.AbstractSlot (slotSig, flags, _, _) -> Choice1Of2 (parseMember slotSig flags) | SynMemberDefn.AbstractSlot (slotSig, flags, _, _) -> parseMember slotSig flags
| SynMemberDefn.Inherit (baseType, _asIdent, _) -> Choice2Of2 baseType
| _ -> failwith $"Unrecognised member definition: %+A{defn}" | _ -> failwith $"Unrecognised member definition: %+A{defn}"
) )
| _ -> failwith $"Unrecognised SynTypeDefnRepr for an interface type: %+A{synTypeDefnRepr}" | _ -> failwith $"Unrecognised SynTypeDefnRepr for an interface type: %+A{synTypeDefnRepr}"
|> List.partitionChoice |> List.partitionChoice
let members, properties = members |> List.partitionChoice
{ {
Members = members Members = members
Properties = properties Properties = properties
Name = interfaceName Name = interfaceName
Inherits = inherits
Attributes = attrs Attributes = attrs
Generics = typars Generics = typars
Accessibility = accessibility Accessibility = accessibility
@@ -463,30 +435,15 @@ module internal AstHelper =
{ {
Type = ty Type = ty
Name = id Name = id
GenericsOfParent = typars
} }
) )
Generics = typars
} }
) )
cases, typars, access cases, typars, access
| _ -> failwithf "Failed to get union cases for type that was: %+A" repr | _ -> failwithf "Failed to get union cases for type that was: %+A" repr
let getRecordFields (SynTypeDefn.SynTypeDefn (typeInfo, repr, _, _, _, _)) : AdtNode list = let getRecordFields (SynTypeDefn.SynTypeDefn (_, repr, _, _, _, _)) : AdtNode list =
let (SynComponentInfo.SynComponentInfo (typeParams = typars)) = typeInfo
let typars =
match typars with
| None -> []
| Some (SynTyparDecls.PrefixList (decls, _)) -> decls
| Some (SynTyparDecls.SinglePrefix (l, _)) -> [ l ]
| Some (SynTyparDecls.PostfixList (decls, constraints, _)) ->
if not constraints.IsEmpty then
failwith "Constrained type parameters not currently supported"
decls
match repr with match repr with
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_, fields, _), _) -> | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_, fields, _), _) ->
fields fields
@@ -494,7 +451,6 @@ module internal AstHelper =
{ {
Name = ident Name = ident
Type = ty Type = ty
GenericsOfParent = typars
} }
) )
| _ -> failwithf "Failed to get record elements for type that was: %+A" repr | _ -> failwithf "Failed to get record elements for type that was: %+A" repr
@@ -507,11 +463,6 @@ module internal SynTypePatterns =
Some innerType Some innerType
| _ -> None | _ -> None
let (|UnitType|_|) (fieldType : SynType) : unit option =
match fieldType with
| SynType.LongIdent ident when AstHelper.isUnitIdent ident -> Some ()
| _ -> None
let (|ListType|_|) (fieldType : SynType) = let (|ListType|_|) (fieldType : SynType) =
match fieldType with match fieldType with
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isListIdent ident -> | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isListIdent ident ->

View File

@@ -35,10 +35,8 @@ module internal CataGenerator =
/// The relationship this field has with the parent type (or the /// The relationship this field has with the parent type (or the
/// recursive knot of parent types) /// recursive knot of parent types)
Description : FieldDescription Description : FieldDescription
/// Any generic parameters this field consumes. /// Any generic parameters this field consumes
/// This only makes sense in the context of a UnionAnalysis: RequiredGenerics : SynType list option
/// it is an index into the parent Union's collection of generic parameters.
RequiredGenerics : int list option
} }
type CataUnionRecordField = (Ident * CataUnionBasicField) list type CataUnionRecordField = (Ident * CataUnionBasicField) list
@@ -121,10 +119,12 @@ module internal CataGenerator =
(userProvidedTypars : SynTyparDecl list) (userProvidedTypars : SynTyparDecl list)
(allArtificialTypars : SynType list) (allArtificialTypars : SynType list)
(relevantTypar : SynType) (relevantTypar : SynType)
(analysis : UnionAnalysis) (unionType : SynTypeDefn)
: SynBinding : SynBinding
= =
let relevantTypeName = analysis.ParentTypeName let relevantTypeName =
match unionType with
| SynTypeDefn.SynTypeDefn (SynComponentInfo.SynComponentInfo (longId = id), _, _, _, _, _) -> List.last id
let allArtificialTyparNames = let allArtificialTyparNames =
allArtificialTypars allArtificialTypars
@@ -134,11 +134,7 @@ module internal CataGenerator =
| _ -> failwith "logic error in generator" | _ -> failwith "logic error in generator"
) )
let userProvidedTyparsForCase = let userProvidedTypars =
analysis.Typars
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, ty)) -> SynType.Var (ty, range0))
let userProvidedTyparsForCata =
userProvidedTypars userProvidedTypars
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, ty)) -> SynType.Var (ty, range0)) |> List.map (fun (SynTyparDecl.SynTyparDecl (_, ty)) -> SynType.Var (ty, range0))
@@ -149,7 +145,7 @@ module internal CataGenerator =
let inputObjectType = let inputObjectType =
let baseType = let baseType =
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent relevantTypeName) SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ relevantTypeName ])
if userProvidedTypars.Length = 0 then if userProvidedTypars.Length = 0 then
baseType baseType
@@ -157,7 +153,7 @@ module internal CataGenerator =
SynType.App ( SynType.App (
baseType, baseType,
Some range0, Some range0,
userProvidedTyparsForCase, userProvidedTypars,
List.replicate (userProvidedTypars.Length - 1) range0, List.replicate (userProvidedTypars.Length - 1) range0,
Some range0, Some range0,
false, false,
@@ -174,7 +170,7 @@ module internal CataGenerator =
SynType.App ( SynType.App (
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ cataName ]), SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ cataName ]),
Some range0, Some range0,
userProvidedTyparsForCata @ allArtificialTypars, userProvidedTypars @ allArtificialTypars,
List.replicate (userProvidedTypars.Length + allArtificialTypars.Length - 1) range0, List.replicate (userProvidedTypars.Length + allArtificialTypars.Length - 1) range0,
Some range0, Some range0,
false, false,
@@ -198,8 +194,8 @@ module internal CataGenerator =
None None
), ),
SynPat.CreateLongIdent ( SynPat.CreateLongIdent (
SynLongIdent.CreateString ("run" + List.last(relevantTypeName).idText), SynLongIdent.CreateString ("run" + relevantTypeName.idText),
[ SynPat.CreateParen cataObject ; SynPat.CreateParen inputObject ] [ SynPat.CreateParen (cataObject) ; SynPat.CreateParen inputObject ]
), ),
Some (SynBindingReturnInfo.Create relevantTypar), Some (SynBindingReturnInfo.Create relevantTypar),
SynExpr.CreateTyped ( SynExpr.CreateTyped (
@@ -223,7 +219,10 @@ module internal CataGenerator =
SynExpr.CreateLongIdent (SynLongIdent.Create [ "instructions" ; "Add" ]), SynExpr.CreateLongIdent (SynLongIdent.Create [ "instructions" ; "Add" ]),
SynExpr.CreateParen ( SynExpr.CreateParen (
SynExpr.CreateApp ( SynExpr.CreateApp (
SynExpr.CreateLongIdent analysis.AssociatedProcessInstruction, SynExpr.CreateLongIdent (
SynLongIdent.Create
[ "Instruction" ; "Process__" + relevantTypeName.idText ]
),
SynExpr.CreateLongIdent (SynLongIdent.CreateString "x") SynExpr.CreateLongIdent (SynLongIdent.CreateString "x")
) )
) )
@@ -304,19 +303,14 @@ module internal CataGenerator =
/// Get the fields of this particular union case, and describe their relation to the /// Get the fields of this particular union case, and describe their relation to the
/// recursive knot of user-provided DUs for which we are creating a cata. /// recursive knot of user-provided DUs for which we are creating a cata.
let analyse let analyse
(availableGenerics : SynTyparDecl list)
(allRecordTypes : SynTypeDefn list) (allRecordTypes : SynTypeDefn list)
(allUnionTypes : SynTypeDefn list) (allUnionTypes : SynTypeDefn list)
(argIndex : int) (argIndex : int)
(fields : AdtNode list) (fields : AdtNode list)
: CataUnionBasicField list : CataUnionBasicField list
= =
let availableGenerics =
availableGenerics
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident)
let rec go (prefix : string) (name : Ident option) (ty : SynType) : CataUnionBasicField = let rec go (prefix : string) (name : Ident option) (ty : SynType) : CataUnionBasicField =
let dealWithPrimitive (typeArgs : int list option) (ty : SynType) (typeName : LongIdent) = let dealWithPrimitive (typeArgs : SynType list option) (ty : SynType) (typeName : LongIdent) =
let key = typeName |> List.map _.idText |> String.concat "/" let key = typeName |> List.map _.idText |> String.concat "/"
let isKnownUnion = let isKnownUnion =
@@ -347,7 +341,7 @@ module internal CataGenerator =
RequiredGenerics = typeArgs RequiredGenerics = typeArgs
} }
let rec dealWithType (typeArgs : int list option) (stripped : SynType) = let rec dealWithType (typeArgs : SynType list option) (stripped : SynType) =
match stripped with match stripped with
| ListType child -> | ListType child ->
let gone = go (prefix + "_") None child let gone = go (prefix + "_") None child
@@ -388,20 +382,7 @@ module internal CataGenerator =
| SynType.App (ty, _, childTypeArgs, _, _, _, _) -> | SynType.App (ty, _, childTypeArgs, _, _, _, _) ->
match typeArgs with match typeArgs with
| Some _ -> failwithf "Nested applications of types not supported in %+A" ty | Some _ -> failwithf "Nested applications of types not supported in %+A" ty
| None -> | None -> dealWithType (Some childTypeArgs) (SynType.stripOptionalParen ty)
let childTypeArgs =
childTypeArgs
|> List.map (fun generic ->
let generic =
match generic with
| SynType.Var (SynTypar.SynTypar (name, _, _), _) -> name
| _ -> failwithf "Unrecognised generic arg: %+A" generic
availableGenerics
|> List.findIndex (fun knownGeneric -> knownGeneric.idText = generic.idText)
)
dealWithType (Some childTypeArgs) (SynType.stripOptionalParen ty)
| SynType.LongIdent (SynLongIdent.SynLongIdent (ty, _, _)) -> dealWithPrimitive typeArgs stripped ty | SynType.LongIdent (SynLongIdent.SynLongIdent (ty, _, _)) -> dealWithPrimitive typeArgs stripped ty
| SynType.Var (typar, _) -> | SynType.Var (typar, _) ->
{ {
@@ -476,8 +457,6 @@ module internal CataGenerator =
{ {
Name = name |> Option.map Ident.lowerFirstLetter Name = name |> Option.map Ident.lowerFirstLetter
Type = ty Type = ty
// TODO this is definitely wrong
GenericsOfParent = []
} }
) )
@@ -520,7 +499,6 @@ module internal CataGenerator =
false, false,
range0 range0
) )
GenericsOfParent = union.Typars
} }
|> List.singleton |> List.singleton
} }
@@ -533,28 +511,12 @@ module internal CataGenerator =
/// Build the DU which defines the states our state machine can be in. /// Build the DU which defines the states our state machine can be in.
let createInstructionType (analysis : UnionAnalysis list) : SynTypeDefn = let createInstructionType (analysis : UnionAnalysis list) : SynTypeDefn =
let parentGenerics =
analysis
|> List.collect _.Typars
|> 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))
)
// One union case for each union type, and then // One union case for each union type, and then
// a union case for each union case which contains a recursive reference. // a union case for each union case which contains a recursive reference.
let casesFromProcess : SynUnionCase list = let casesFromProcess : SynUnionCase list =
baseCases analysis baseCases analysis
|> List.map (fun unionCase -> |> List.map (fun unionCase ->
let fields = SynUnionCase.Create (unionCase.Name, unionCase.Fields |> List.map (fun f -> SynField.Create f.Type))
unionCase.Fields
|> List.map (fun field ->
// TODO: adjust type parameters
SynField.Create field.Type
)
SynUnionCase.Create (unionCase.Name, fields)
) )
let casesFromCases = let casesFromCases =
@@ -566,22 +528,14 @@ module internal CataGenerator =
let cases = casesFromProcess @ casesFromCases let cases = casesFromProcess @ casesFromCases
let typars = let typars =
let count = analysis |> List.map (fun x -> List.length x.Typars) |> List.max // TODO: deduplicate names where we have the same generic across multiple DUs
analysis
if analysis |> List.forall (fun x -> x.Typars.IsEmpty) then |> List.collect _.Typars
None |> fun x ->
else if x.IsEmpty then
None
let typars = else
analysis Some (SynTyparDecls.PostfixList (x, [], range0))
|> List.collect _.Typars
|> 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))
)
Some (SynTyparDecls.PostfixList (typars, [], range0))
SynTypeDefn.SynTypeDefn ( SynTypeDefn.SynTypeDefn (
SynComponentInfo.SynComponentInfo ( SynComponentInfo.SynComponentInfo (
@@ -679,26 +633,7 @@ module internal CataGenerator =
[ SynType.Var (generics.[getNameKeyUnion ty], range0) ], [ SynType.Var (generics.[getNameKeyUnion ty], range0) ],
true true
) )
| FieldDescription.NonRecursive ty -> | FieldDescription.NonRecursive ty -> 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.Fun (
SynType.SignatureParameter ( SynType.SignatureParameter (
@@ -785,11 +720,7 @@ module internal CataGenerator =
let userInputGenerics = let userInputGenerics =
analysis.Typars analysis.Typars
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText) |> List.map (fun (SynTyparDecl.SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|> List.distinct
|> List.map (fun i ->
SynType.Var (SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false), range0)
)
let ty = let ty =
SynType.App ( SynType.App (
@@ -820,11 +751,9 @@ module internal CataGenerator =
// A "real" generic for each generic in the user-provided type // A "real" generic for each generic in the user-provided type
let genericsFromUserInput = let genericsFromUserInput =
analysis analysis
|> List.collect _.Typars |> List.collect (fun analysis ->
|> List.map (fun (SynTyparDecl.SynTyparDecl (_, SynTypar.SynTypar (ident, _, _))) -> ident.idText) // TODO: deduplicate generics with the same name from different cases
|> List.distinct analysis.Typars
|> List.map (fun i ->
SynTyparDecl.SynTyparDecl ([], SynTypar.SynTypar (Ident.Create i, TyparStaticReq.None, false))
) )
let genericsFromCata = let genericsFromCata =
@@ -877,18 +806,21 @@ module internal CataGenerator =
prod.Fields prod.Fields
|> List.indexed |> List.indexed
|> List.collect (fun (i, node) -> |> List.collect (fun (i, node) ->
let availableGenerics =
match node.Type with
| SynType.App (_, _, vars, _, _, _, _) -> vars
| _ -> []
match getNameUnion node.Type with match getNameUnion node.Type with
| None -> | None ->
analyse typars allRecordTypes allUnionTypes i [ node ] analyse allRecordTypes allUnionTypes i [ node ] |> List.map CataUnionField.Basic
|> List.map CataUnionField.Basic
| Some name -> | Some name ->
match Map.tryFind (List.last(name).idText) recordTypes with match Map.tryFind (List.last(name).idText) recordTypes with
| None -> | None ->
analyse typars allRecordTypes allUnionTypes i [ node ] analyse allRecordTypes allUnionTypes i [ node ] |> List.map CataUnionField.Basic
|> List.map CataUnionField.Basic
| Some fields -> | Some fields ->
List.zip fields (analyse typars allRecordTypes allUnionTypes i fields) List.zip fields (analyse allRecordTypes allUnionTypes i fields)
|> List.map (fun (field, analysis) -> Option.get field.Name, analysis) |> List.map (fun (field, analysis) -> Option.get field.Name, analysis)
|> CataUnionField.Record |> CataUnionField.Record
|> List.singleton |> List.singleton
@@ -1378,20 +1310,16 @@ module internal CataGenerator =
None None
) )
let userSuppliedGenerics = // A generic for each DU case, and a generic for each generic in the DU
analysis let genericCount = analysis.Length + (analysis |> List.sumBy _.Typars.Length)
|> 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))
let instructionsArrType = let instructionsArrType =
if not userSuppliedGenerics.IsEmpty then if genericCount > analysis.Length then
SynType.App ( SynType.App (
SynType.CreateLongIdent "Instruction", SynType.CreateLongIdent "Instruction",
Some range0, Some range0,
userSuppliedGenerics |> List.map (fun x -> SynType.Var (x, range0)), List.replicate (genericCount - analysis.Length) (SynType.Anon range0),
List.replicate (userSuppliedGenerics.Length - 1) range0, List.replicate (genericCount - analysis.Length - 1) range0,
Some range0, Some range0,
false, false,
range0 range0
@@ -1399,14 +1327,6 @@ module internal CataGenerator =
else else
SynType.CreateLongIdent "Instruction" SynType.CreateLongIdent "Instruction"
let cataGenerics =
[
for generic in userSuppliedGenerics do
yield SynType.Var (generic, range0)
for case in analysis do
yield SynType.Var (SynTypar.SynTypar (case.GenericName, TyparStaticReq.None, false), range0)
]
let headPat = let headPat =
SynPat.LongIdent ( SynPat.LongIdent (
SynLongIdent.CreateString "loop", SynLongIdent.CreateString "loop",
@@ -1420,8 +1340,8 @@ module internal CataGenerator =
SynType.App ( SynType.App (
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ cataTypeName ]), SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ cataTypeName ]),
Some range0, Some range0,
cataGenerics, List.replicate genericCount (SynType.Anon range0),
List.replicate (cataGenerics.Length - 1) range0, List.replicate (genericCount - 1) range0,
Some range0, Some range0,
false, false,
range0 range0
@@ -1536,20 +1456,7 @@ module internal CataGenerator =
SynPat.Named (SynIdent.SynIdent (unionCase.StackName, None), false, None, range0), SynPat.Named (SynIdent.SynIdent (unionCase.StackName, None), false, None, range0),
None, None,
SynExpr.CreateApp ( SynExpr.CreateApp (
SynExpr.TypeApp ( SynExpr.CreateLongIdent (SynLongIdent.CreateString "ResizeArray"),
SynExpr.CreateIdent (Ident.Create "ResizeArray"),
range0,
[
SynType.Var (
SynTypar.SynTypar (unionCase.GenericName, TyparStaticReq.None, false),
range0
)
],
[],
Some range0,
range0,
range0
),
SynExpr.CreateConst SynConst.Unit SynExpr.CreateConst SynConst.Unit
), ),
range0, range0,
@@ -1619,21 +1526,15 @@ module internal CataGenerator =
|> fun x -> SynType.Var (x, range0) |> fun x -> SynType.Var (x, range0)
) )
let userProvidedGenerics = let userProvidedGenerics = analysis |> List.collect (fun x -> x.Typars)
analysis
|> List.collect _.Typars
|> 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))
)
let runFunctions = let runFunctions =
List.zip analysis allTypars List.zip allUnionTypes allTypars
|> List.map (fun (analysis, relevantTypar) -> |> List.map (fun (unionType, relevantTypar) ->
createRunFunction cataName userProvidedGenerics allTypars relevantTypar analysis createRunFunction cataName userProvidedGenerics allTypars relevantTypar unionType
) )
let cataStructures = let cataStructures =
createCataStructure analysis createCataStructure analysis
|> List.map (fun repr -> SynModuleDecl.Types ([ repr ], range0)) |> List.map (fun repr -> SynModuleDecl.Types ([ repr ], range0))

View File

@@ -1,6 +1,8 @@
namespace WoofWare.Myriad.Plugins namespace WoofWare.Myriad.Plugins
open System
open System.Net.Http open System.Net.Http
open System.Text
open Fantomas.FCS.Syntax open Fantomas.FCS.Syntax
open Fantomas.FCS.SyntaxTrivia open Fantomas.FCS.SyntaxTrivia
open Fantomas.FCS.Xml open Fantomas.FCS.Xml
@@ -80,50 +82,34 @@ module internal HttpClientGenerator =
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "Get" | "Get"
| "GetAttribute" | "GetAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Get"
| "WoofWare.Myriad.Plugins.RestEase.GetAttribute"
| "RestEase.Get" | "RestEase.Get"
| "RestEase.GetAttribute" -> Some (HttpMethod.Get, attr.ArgExpr) | "RestEase.GetAttribute" -> Some (HttpMethod.Get, attr.ArgExpr)
| "Post" | "Post"
| "PostAttribute" | "PostAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Post"
| "WoofWare.Myriad.Plugins.RestEase.PostAttribute"
| "RestEase.Post" | "RestEase.Post"
| "RestEase.PostAttribute" -> Some (HttpMethod.Post, attr.ArgExpr) | "RestEase.PostAttribute" -> Some (HttpMethod.Post, attr.ArgExpr)
| "Put" | "Put"
| "PutAttribute" | "PutAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Put"
| "WoofWare.Myriad.Plugins.RestEase.PutAttribute"
| "RestEase.Put" | "RestEase.Put"
| "RestEase.PutAttribute" -> Some (HttpMethod.Put, attr.ArgExpr) | "RestEase.PutAttribute" -> Some (HttpMethod.Put, attr.ArgExpr)
| "Delete" | "Delete"
| "DeleteAttribute" | "DeleteAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Delete"
| "WoofWare.Myriad.Plugins.RestEase.DeleteAttribute"
| "RestEase.Delete" | "RestEase.Delete"
| "RestEase.DeleteAttribute" -> Some (HttpMethod.Delete, attr.ArgExpr) | "RestEase.DeleteAttribute" -> Some (HttpMethod.Delete, attr.ArgExpr)
| "Head" | "Head"
| "HeadAttribute" | "HeadAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Head"
| "WoofWare.Myriad.Plugins.RestEase.HeadAttribute"
| "RestEase.Head" | "RestEase.Head"
| "RestEase.HeadAttribute" -> Some (HttpMethod.Head, attr.ArgExpr) | "RestEase.HeadAttribute" -> Some (HttpMethod.Head, attr.ArgExpr)
| "Options" | "Options"
| "OptionsAttribute" | "OptionsAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Options"
| "WoofWare.Myriad.Plugins.RestEase.OptionsAttribute"
| "RestEase.Options" | "RestEase.Options"
| "RestEase.OptionsAttribute" -> Some (HttpMethod.Options, attr.ArgExpr) | "RestEase.OptionsAttribute" -> Some (HttpMethod.Options, attr.ArgExpr)
| "Patch" | "Patch"
| "PatchAttribute" | "PatchAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Patch"
| "WoofWare.Myriad.Plugins.RestEase.PatchAttribute"
| "RestEase.Patch" | "RestEase.Patch"
| "RestEase.PatchAttribute" -> Some (HttpMethod.Patch, attr.ArgExpr) | "RestEase.PatchAttribute" -> Some (HttpMethod.Patch, attr.ArgExpr)
| "Trace" | "Trace"
| "TraceAttribute" | "TraceAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Trace"
| "WoofWare.Myriad.Plugins.RestEase.TraceAttribute"
| "RestEase.Trace" | "RestEase.Trace"
| "RestEase.TraceAttribute" -> Some (HttpMethod.Trace, attr.ArgExpr) | "RestEase.TraceAttribute" -> Some (HttpMethod.Trace, attr.ArgExpr)
| _ -> None | _ -> None
@@ -141,8 +127,7 @@ module internal HttpClientGenerator =
|> List.choose (fun attr -> |> List.choose (fun attr ->
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "Header" | "Header"
| "RestEase.Header" | "RestEase.Header" ->
| "WoofWare.Myriad.Plugins.RestEase.Header" ->
match attr.ArgExpr with match attr.ArgExpr with
| SynExpr.Paren (SynExpr.Tuple (_, [ v1 ; v2 ], _, _), _, _, _) -> | SynExpr.Paren (SynExpr.Tuple (_, [ v1 ; v2 ], _, _), _, _, _) ->
Some [ SynExpr.stripOptionalParen v1 ; SynExpr.stripOptionalParen v2 ] Some [ SynExpr.stripOptionalParen v1 ; SynExpr.stripOptionalParen v2 ]
@@ -308,27 +293,6 @@ module internal HttpClientGenerator =
| None -> failwith "Unable to get parameter variable name from anonymous parameter" | None -> failwith "Unable to get parameter variable name from anonymous parameter"
| Some id -> id | Some id -> id
let urlSeparator =
// apparent Myriad bug: `IndexOf '?'` gets formatted as `IndexOf ?` which is clearly wrong
let questionMark =
SynExpr.CreateParen (
SynExpr.CreateApp (
SynExpr.CreateIdentString "char",
SynExpr.CreateConst (SynConst.Int32 63)
)
)
let containsQuestion =
info.UrlTemplate
|> SynExpr.callMethodArg "IndexOf" questionMark
|> SynExpr.greaterThanOrEqual (SynExpr.CreateConst (SynConst.Int32 0))
SynExpr.ifThenElse
containsQuestion
(SynExpr.CreateConst (SynConst.CreateString "?"))
(SynExpr.CreateConst (SynConst.CreateString "&"))
|> SynExpr.CreateParen
let prefix = let prefix =
SynExpr.CreateIdent firstValueId SynExpr.CreateIdent firstValueId
|> SynExpr.toString firstValue.Type |> SynExpr.toString firstValue.Type
@@ -337,7 +301,7 @@ module internal HttpClientGenerator =
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ]) SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Web" ; "HttpUtility" ; "UrlEncode" ])
) )
|> SynExpr.CreateParen |> SynExpr.CreateParen
|> SynExpr.plus (SynExpr.plus urlSeparator (SynExpr.CreateConstString (firstKey + "="))) |> SynExpr.plus (SynExpr.CreateConstString ("?" + firstKey + "="))
(prefix, queryParams) (prefix, queryParams)
||> List.fold (fun uri (paramKey, paramValue) -> ||> List.fold (fun uri (paramKey, paramValue) ->
@@ -745,10 +709,6 @@ module internal HttpClientGenerator =
attrs attrs
|> List.choose (fun attr -> |> List.choose (fun attr ->
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "RestEase.Query"
| "RestEase.QueryAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Query"
| "WoofWare.Myriad.Plugins.RestEase.QueryAttribute"
| "Query" | "Query"
| "QueryAttribute" -> | "QueryAttribute" ->
match attr.ArgExpr with match attr.ArgExpr with
@@ -757,10 +717,6 @@ module internal HttpClientGenerator =
Some (HttpAttribute.Query (Some s)) Some (HttpAttribute.Query (Some s))
| SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Query attribute: %+A{a}" | SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Query attribute: %+A{a}"
| _ -> None | _ -> None
| "RestEase.Path"
| "RestEase.PathAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Path"
| "WoofWare.Myriad.Plugins.RestEase.PathAttribute"
| "Path" | "Path"
| "PathAttribute" -> | "PathAttribute" ->
match attr.ArgExpr with match attr.ArgExpr with
@@ -769,10 +725,6 @@ module internal HttpClientGenerator =
| SynExpr.Const (SynConst.Unit, _) -> Some (HttpAttribute.Path PathSpec.MatchArgName) | SynExpr.Const (SynConst.Unit, _) -> Some (HttpAttribute.Path PathSpec.MatchArgName)
| SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Path attribute: %+A{a}" | SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Path attribute: %+A{a}"
| _ -> None | _ -> None
| "RestEase.Body"
| "RestEase.BodyAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Body"
| "WoofWare.Myriad.Plugins.RestEase.BodyAttribute"
| "Body" | "Body"
| "BodyAttribute" -> | "BodyAttribute" ->
match attr.ArgExpr with match attr.ArgExpr with
@@ -788,10 +740,8 @@ module internal HttpClientGenerator =
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "BasePath" | "BasePath"
| "RestEase.BasePath" | "RestEase.BasePath"
| "WoofWare.Myriad.Plugins.RestEase.BasePath"
| "BasePathAttribute" | "BasePathAttribute"
| "RestEase.BasePathAttribute" | "RestEase.BasePathAttribute" -> Some attr.ArgExpr
| "WoofWare.Myriad.Plugins.RestEase.BasePathAttribute" -> Some attr.ArgExpr
| _ -> None | _ -> None
) )
@@ -801,10 +751,8 @@ module internal HttpClientGenerator =
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "BaseAddress" | "BaseAddress"
| "RestEase.BaseAddress" | "RestEase.BaseAddress"
| "WoofWare.Myriad.Plugins.RestEase.BaseAddress"
| "BaseAddressAttribute" | "BaseAddressAttribute"
| "RestEase.BaseAddressAttribute" | "RestEase.BaseAddressAttribute" -> Some attr.ArgExpr
| "WoofWare.Myriad.Plugins.RestEase.BaseAddressAttribute" -> Some attr.ArgExpr
| _ -> None | _ -> None
) )
@@ -816,10 +764,6 @@ module internal HttpClientGenerator =
= =
let interfaceType = AstHelper.parseInterface interfaceType let interfaceType = AstHelper.parseInterface interfaceType
if not (List.isEmpty interfaceType.Inherits) then
failwith
"HttpClientGenerator does not support inheritance. Remove the `inherit` keyword if you want to use this generator."
let constantHeaders = let constantHeaders =
interfaceType.Attributes interfaceType.Attributes
|> extractHeaderInformation |> extractHeaderInformation

View File

@@ -21,9 +21,6 @@ module internal InterfaceMockGenerator =
| None -> failwith "Expected record field to have a name, but it was somehow anonymous" | None -> failwith "Expected record field to have a name, but it was somehow anonymous"
| Some id -> id | Some id -> id
[<RequireQualifiedAccess>]
type private KnownInheritance = | IDisposable
let createType let createType
(spec : GenerateMockOutputSpec) (spec : GenerateMockOutputSpec)
(name : string) (name : string)
@@ -32,20 +29,6 @@ module internal InterfaceMockGenerator =
(fields : SynField list) (fields : SynField list)
: SynModuleDecl : SynModuleDecl
= =
let inherits =
interfaceType.Inherits
|> Seq.map (fun ty ->
match ty with
| SynType.LongIdent (SynLongIdent.SynLongIdent (name, _, _)) ->
match name |> List.map _.idText with
| [] -> failwith "Unexpected empty identifier in inheritance declaration"
| [ "IDisposable" ]
| [ "System" ; "IDisposable" ] -> KnownInheritance.IDisposable
| _ -> failwithf "Unrecognised inheritance identifier: %+A" name
| x -> failwithf "Unrecognised type in inheritance: %+A" x
)
|> Set.ofSeq
let synValData = let synValData =
{ {
SynMemberFlags.IsInstance = false SynMemberFlags.IsInstance = false
@@ -107,23 +90,6 @@ module internal InterfaceMockGenerator =
) )
|> SynBindingReturnInfo.Create |> SynBindingReturnInfo.Create
let constructorFields =
let extras =
if inherits.Contains KnownInheritance.IDisposable then
let unitFun = SynExpr.createLambda "_" SynExpr.CreateUnit
[
(SynLongIdent.CreateFromLongIdent [ Ident.Create "Dispose" ], true), Some unitFun
]
else
[]
let nonExtras =
fields
|> List.map (fun field -> (SynLongIdent.CreateFromLongIdent [ getName field ], true), Some failwithFun)
extras @ nonExtras
let constructor = let constructor =
SynMemberDefn.Member ( SynMemberDefn.Member (
SynBinding.SynBinding ( SynBinding.SynBinding (
@@ -136,7 +102,12 @@ module internal InterfaceMockGenerator =
SynValData.SynValData (Some synValData, SynValInfo.Empty, None), SynValData.SynValData (Some synValData, SynValInfo.Empty, None),
constructorIdent, constructorIdent,
Some constructorReturnType, Some constructorReturnType,
AstHelper.instantiateRecord constructorFields, AstHelper.instantiateRecord (
fields
|> List.map (fun field ->
((SynLongIdent.CreateFromLongIdent [ getName field ], true), Some failwithFun)
)
),
range0, range0,
DebugPointAtBinding.Yes range0, DebugPointAtBinding.Yes range0,
{ SynExpr.synBindingTriviaZero true with { SynExpr.synBindingTriviaZero true with
@@ -146,21 +117,6 @@ module internal InterfaceMockGenerator =
range0 range0
) )
let fields =
let extras =
if inherits.Contains KnownInheritance.IDisposable then
[
SynField.Create (
SynType.CreateFun (SynType.CreateUnit, SynType.CreateUnit),
Ident.Create "Dispose",
xmldoc = PreXmlDoc.Create " Implementation of IDisposable.Dispose"
)
]
else
[]
extras @ fields
let interfaceMembers = let interfaceMembers =
let members = let members =
interfaceType.Members interfaceType.Members
@@ -194,9 +150,7 @@ module internal InterfaceMockGenerator =
|> List.mapi (fun i arg -> |> List.mapi (fun i arg ->
arg.Args arg.Args
|> List.mapi (fun j arg -> |> List.mapi (fun j arg ->
match arg.Type with SynArgInfo.CreateIdString $"arg_%i{i}_%i{j}"
| UnitType -> SynArgInfo.SynArgInfo ([], false, None)
| _ -> SynArgInfo.CreateIdString $"arg_%i{i}_%i{j}"
) )
) )
], ],
@@ -211,18 +165,10 @@ module internal InterfaceMockGenerator =
|> List.mapi (fun i tupledArgs -> |> List.mapi (fun i tupledArgs ->
let args = let args =
tupledArgs.Args tupledArgs.Args
|> List.mapi (fun j ty -> |> List.mapi (fun j _ -> SynPat.CreateNamed (Ident.Create $"arg_%i{i}_%i{j}"))
match ty.Type with
| UnitType -> SynPat.Const (SynConst.Unit, range0)
| _ -> SynPat.CreateNamed (Ident.Create $"arg_%i{i}_%i{j}")
)
match args with SynPat.Tuple (false, args, List.replicate (args.Length - 1) range0, range0)
| [] -> failwith "somehow got no args at all" |> SynPat.CreateParen
| [ arg ] -> arg
| args ->
SynPat.Tuple (false, args, List.replicate (args.Length - 1) range0, range0)
|> SynPat.CreateParen
|> fun i -> if tupledArgs.HasParen then SynPat.Paren (i, range0) else i |> fun i -> if tupledArgs.HasParen then SynPat.Paren (i, range0) else i
) )
@@ -241,11 +187,7 @@ module internal InterfaceMockGenerator =
memberInfo.Args memberInfo.Args
|> List.mapi (fun i args -> |> List.mapi (fun i args ->
args.Args args.Args
|> List.mapi (fun j arg -> |> List.mapi (fun j args -> SynExpr.CreateIdentString $"arg_%i{i}_%i{j}")
match arg.Type with
| UnitType -> SynExpr.CreateConst SynConst.Unit
| _ -> SynExpr.CreateIdentString $"arg_%i{i}_%i{j}"
)
|> SynExpr.CreateParenedTuple |> SynExpr.CreateParenedTuple
) )
@@ -322,100 +264,11 @@ module internal InterfaceMockGenerator =
| Some (SynAccess.Internal _), _ -> SynAccess.Internal range0 | Some (SynAccess.Internal _), _ -> SynAccess.Internal range0
| Some (SynAccess.Private _), _ -> SynAccess.Private range0 | Some (SynAccess.Private _), _ -> SynAccess.Private range0
let extraInterfaces =
inherits
|> Seq.map (fun inheritance ->
match inheritance with
| KnownInheritance.IDisposable ->
let valData =
SynValData.SynValData (
Some
{
IsInstance = true
IsDispatchSlot = false
IsOverrideOrExplicitImpl = true
IsFinal = false
GetterOrSetterIsCompilerGenerated = false
MemberKind = SynMemberKind.Member
},
valInfo =
SynValInfo.SynValInfo (
curriedArgInfos =
[
yield
[
SynArgInfo.SynArgInfo (
attributes = [],
optional = false,
ident = None
)
]
],
returnInfo =
SynArgInfo.SynArgInfo (attributes = [], optional = false, ident = None)
),
thisIdOpt = None
)
let headArgs = [ SynPat.Const (SynConst.Unit, range0) ]
let headPat =
SynPat.LongIdent (
SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; Ident.Create "Dispose" ],
None,
None,
SynArgPats.Pats headArgs,
None,
range0
)
let binding =
SynBinding.SynBinding (
None,
SynBindingKind.Normal,
false,
false,
[],
PreXmlDoc.Empty,
valData,
headPat,
Some (
SynBindingReturnInfo.SynBindingReturnInfo (
SynType.Unit (),
range0,
[],
SynBindingReturnInfoTrivia.Zero
)
),
SynExpr.CreateApp (
SynExpr.CreateLongIdent (SynLongIdent.Create [ "this" ; "Dispose" ]),
SynExpr.CreateUnit
),
range0,
DebugPointAtBinding.Yes range0,
{
LeadingKeyword = SynLeadingKeyword.Member range0
InlineKeyword = None
EqualsRange = Some range0
}
)
let mem = SynMemberDefn.Member (binding, range0)
SynMemberDefn.Interface (
SynType.CreateLongIdent (SynLongIdent.Create [ "System" ; "IDisposable" ]),
Some range0,
Some [ mem ],
range0
)
)
|> Seq.toList
let record = let record =
{ {
Name = Ident.Create name Name = Ident.Create name
Fields = fields Fields = fields
Members = Some ([ constructor ; interfaceMembers ] @ extraInterfaces) Members = Some [ constructor ; interfaceMembers ]
XmlDoc = Some xmlDoc XmlDoc = Some xmlDoc
Generics = interfaceType.Generics Generics = interfaceType.Generics
Accessibility = Some access Accessibility = Some access
@@ -480,6 +333,7 @@ module internal InterfaceMockGenerator =
let typeDecl = createType spec name interfaceType docString fields let typeDecl = createType spec name interfaceType docString fields
SynModuleOrNamespace.CreateNamespace ( SynModuleOrNamespace.CreateNamespace (
namespaceId, namespaceId,
decls = (opens |> List.map SynModuleDecl.CreateOpen) @ [ typeDecl ] decls = (opens |> List.map SynModuleDecl.CreateOpen) @ [ typeDecl ]

View File

@@ -311,19 +311,3 @@ module internal SynExpr =
), ),
x x
) )
/// {y} >= {x}
let greaterThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr =
SynExpr.CreateApp (
SynExpr.CreateAppInfix (
SynExpr.CreateLongIdent (
SynLongIdent.SynLongIdent (
[ Ident.Create "op_GreaterThanOrEqual" ],
[],
[ Some (IdentTrivia.OriginalNotation ">=") ]
)
),
y
),
x
)

View File

@@ -10,7 +10,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.9.3]" /> <PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.8.0]" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -3,18 +3,23 @@
{fetchNuGet}: [ {fetchNuGet}: [
(fetchNuGet { (fetchNuGet {
pname = "fsharp-analyzers"; pname = "fsharp-analyzers";
version = "0.25.0"; version = "0.24.0";
sha256 = "sha256-njfJYi40jNvrD+mgu9LtQw2Omh8P1SSDThesozH0KQY="; sha256 = "sha256-cNaM/yHI28sHDGamKMrU237ltOyrR+8vPNUImB5RxjU=";
}) })
(fetchNuGet { (fetchNuGet {
pname = "fantomas"; pname = "fantomas";
version = "6.3.4"; version = "6.3.0-alpha-007";
sha256 = "sha256-1aWqZynBkQoznenGoP0sbf1PcUXAbcHiWyECuv89xa0="; sha256 = "sha256-uZw6h6k/DS4BcYtK9cv8TLS0H8MZDO3WBaPPTdtTgu0=";
}) })
(fetchNuGet { (fetchNuGet {
pname = "ApiSurface"; pname = "ApiSurface";
version = "4.0.39"; version = "4.0.28";
sha256 = "sha256-I4K5nJbltsfL/1r+KPTIo2wUd30zsCC2pkrnIRnsRHM="; sha256 = "1gg0dqbgbb8aqn2lxi5gf2wq969kgskby5wph6m2b3hdkz7265ak";
})
(fetchNuGet {
pname = "coverlet.collector";
version = "6.0.0";
sha256 = "12j34vrkmph8lspbafnqmfnj2qvysz1jcrks2khw798s6dwv0j90";
}) })
(fetchNuGet { (fetchNuGet {
pname = "Fantomas.Core"; pname = "Fantomas.Core";
@@ -116,11 +121,21 @@
version = "8.0.0"; version = "8.0.0";
sha256 = "0055f69q3hbagqp8gl3nk0vfn4qyqyxsxyy7pd0g7wm3z28byzmx"; sha256 = "0055f69q3hbagqp8gl3nk0vfn4qyqyxsxyy7pd0g7wm3z28byzmx";
}) })
(fetchNuGet {
pname = "Microsoft.CodeCoverage";
version = "17.8.0";
sha256 = "173wjadp3gan4x2jfjchngnc4ca4mb95h1sbb28jydfkfw0z1zvj";
})
(fetchNuGet { (fetchNuGet {
pname = "Microsoft.CodeCoverage"; pname = "Microsoft.CodeCoverage";
version = "17.9.0"; version = "17.9.0";
sha256 = "1gljgi69k0fz8vy8bn6xlyxabj6q4vls2zza9wz7ng6ix3irm89r"; sha256 = "1gljgi69k0fz8vy8bn6xlyxabj6q4vls2zza9wz7ng6ix3irm89r";
}) })
(fetchNuGet {
pname = "Microsoft.NET.Test.Sdk";
version = "17.8.0";
sha256 = "1syvl3g0hbrcgfi9rq6pld8s8hqqww4dflf1lxn59ccddyyx0gmv";
})
(fetchNuGet { (fetchNuGet {
pname = "Microsoft.NET.Test.Sdk"; pname = "Microsoft.NET.Test.Sdk";
version = "17.9.0"; version = "17.9.0";
@@ -266,11 +281,21 @@
version = "8.0.0"; version = "8.0.0";
sha256 = "1gdx7n45wwia3yvang3ls92sk3wrymqcx9p349j8wba2lyjf9m44"; sha256 = "1gdx7n45wwia3yvang3ls92sk3wrymqcx9p349j8wba2lyjf9m44";
}) })
(fetchNuGet {
pname = "Microsoft.TestPlatform.ObjectModel";
version = "17.8.0";
sha256 = "0b0i7lmkrcfvim8i3l93gwqvkhhhfzd53fqfnygdqvkg6np0cg7m";
})
(fetchNuGet { (fetchNuGet {
pname = "Microsoft.TestPlatform.ObjectModel"; pname = "Microsoft.TestPlatform.ObjectModel";
version = "17.9.0"; version = "17.9.0";
sha256 = "1kgsl9w9fganbm9wvlkqgk0ag9hfi58z88rkfybc6kvg78bx89ca"; sha256 = "1kgsl9w9fganbm9wvlkqgk0ag9hfi58z88rkfybc6kvg78bx89ca";
}) })
(fetchNuGet {
pname = "Microsoft.TestPlatform.TestHost";
version = "17.8.0";
sha256 = "0f5jah93kjkvxwmhwb78lw11m9pkkq9fvf135hpymmmpxqbdh97q";
})
(fetchNuGet { (fetchNuGet {
pname = "Microsoft.TestPlatform.TestHost"; pname = "Microsoft.TestPlatform.TestHost";
version = "17.9.0"; version = "17.9.0";
@@ -291,6 +316,11 @@
version = "3.6.133"; version = "3.6.133";
sha256 = "1cdw8krvsnx0n34f7fm5hiiy7bs6h3asvncqcikc0g46l50w2j80"; sha256 = "1cdw8krvsnx0n34f7fm5hiiy7bs6h3asvncqcikc0g46l50w2j80";
}) })
(fetchNuGet {
pname = "NETStandard.Library";
version = "2.0.0";
sha256 = "1bc4ba8ahgk15m8k4nd7x406nhi0kwqzbgjk2dmw52ss553xz7iy";
})
(fetchNuGet { (fetchNuGet {
pname = "NETStandard.Library"; pname = "NETStandard.Library";
version = "2.0.3"; version = "2.0.3";
@@ -308,23 +338,28 @@
}) })
(fetchNuGet { (fetchNuGet {
pname = "NuGet.Common"; pname = "NuGet.Common";
version = "6.9.1"; version = "6.8.0";
sha256 = "0ic3d46r9v05pkczpmskw86yzixm6iwshbw0ya8i2957nhhlymw8"; sha256 = "0l3ij8iwy7wj6s7f93lzi9168r4wz8zyin6a08iwgk7hvq44cia1";
}) })
(fetchNuGet { (fetchNuGet {
pname = "NuGet.Configuration"; pname = "NuGet.Configuration";
version = "6.9.1"; version = "6.8.0";
sha256 = "07z4qgbibpg59j2r05ifnqdyqf2xinm33rx7gjyr1f73kzg01m33"; sha256 = "0x03p408smkmv1gv7pmvsia4lkn0xaj4wfrkl58pjf8bbv51y0yw";
}) })
(fetchNuGet { (fetchNuGet {
pname = "NuGet.Frameworks"; pname = "NuGet.Frameworks";
version = "6.9.1"; version = "6.5.0";
sha256 = "0s3az3ac53icjnmb14hfjcmkvzscvrkm62jgqf48yvsbysyhqm5s"; sha256 = "0s37d1p4md0k6d4cy6sq36f2dgkd9qfbzapxhkvi8awwh0vrynhj";
})
(fetchNuGet {
pname = "NuGet.Frameworks";
version = "6.8.0";
sha256 = "0i2xvhgkjkjr496i3pg8hamwv6505fia45qhn7jg5m01wb3cvsjl";
}) })
(fetchNuGet { (fetchNuGet {
pname = "NuGet.Packaging"; pname = "NuGet.Packaging";
version = "6.9.1"; version = "6.8.0";
sha256 = "0w0arkmzg3qh1brq4vm10zrsjm7nw706ld4y5kqcmvjpd16f4b4y"; sha256 = "031z4s905bxi94h3f0qy4j1b6jxdxgqgpkzqvvpfxch07szxcbim";
}) })
(fetchNuGet { (fetchNuGet {
pname = "NuGet.Protocol"; pname = "NuGet.Protocol";
@@ -333,13 +368,18 @@
}) })
(fetchNuGet { (fetchNuGet {
pname = "NuGet.Versioning"; pname = "NuGet.Versioning";
version = "6.9.1"; version = "6.8.0";
sha256 = "0xrs82dydy9cgxf0qypr01wawwnq1nf6fc7rwisb4y5v4r259fdm"; sha256 = "1sd25h46fd12ng780r02q4ijcx1imkb53kj1y2y7cwg5myh537ks";
}) })
(fetchNuGet { (fetchNuGet {
pname = "NUnit"; pname = "NUnit";
version = "4.1.0"; version = "3.13.3";
sha256 = "0fj6xwgqaxq3mrai86bklclfmjkzf038mrslwfqf4ignaz9f7g5j"; sha256 = "0wdzfkygqnr73s6lpxg5b1pwaqz9f414fxpvpdmf72bvh4jaqzv6";
})
(fetchNuGet {
pname = "NUnit";
version = "4.0.1";
sha256 = "0jgiq3dbwli5r70j0bw7021d69r7bhr58s8kphlpjmf7k47l5pcd";
}) })
(fetchNuGet { (fetchNuGet {
pname = "NUnit3TestAdapter"; pname = "NUnit3TestAdapter";