mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-05 12:08:46 +00:00
Compare commits
37 Commits
WoofWare.M
...
WoofWare.M
Author | SHA1 | Date | |
---|---|---|---|
|
4901e7cdf4 | ||
|
68bd4bc1fd | ||
|
8da0fd01fe | ||
|
18c7a2e920 | ||
|
f371ee59fe | ||
|
f8296e54bc | ||
|
adf497c5db | ||
|
04ecbe6002 | ||
|
7b14e52e9d | ||
|
8e47f39efc | ||
|
6942ba42b9 | ||
|
b98080690d | ||
|
81b7e5361d | ||
|
94b88a4143 | ||
|
ed3ffecb52 | ||
|
c696dcf31f | ||
|
d5bb2726d3 | ||
|
f17290d0f1 | ||
|
35cd94cba1 | ||
|
1b3eb03380 | ||
|
b846ce08a3 | ||
|
4b9f63d374 | ||
|
b9ba07a8a7 | ||
|
e80ed51498 | ||
|
61b07ad802 | ||
|
59369bcb94 | ||
|
072169e4e3 | ||
|
91136a25ab | ||
|
c51038448a | ||
|
09780efb07 | ||
|
f562271c12 | ||
|
e3081c3136 | ||
|
232d2ba5ec | ||
|
f7458f521e | ||
|
bfc25a672b | ||
|
af7fcb3028 | ||
|
91853b1fff |
@@ -3,13 +3,13 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"fantomas": {
|
"fantomas": {
|
||||||
"version": "6.3.0-alpha-008",
|
"version": "6.3.9",
|
||||||
"commands": [
|
"commands": [
|
||||||
"fantomas"
|
"fantomas"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"fsharp-analyzers": {
|
"fsharp-analyzers": {
|
||||||
"version": "0.25.0",
|
"version": "0.26.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"fsharp-analyzers"
|
"fsharp-analyzers"
|
||||||
]
|
]
|
||||||
|
61
.github/workflows/dotnet.yaml
vendored
61
.github/workflows/dotnet.yaml
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-workflow.json
|
||||||
name: .NET
|
name: .NET
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -28,7 +29,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@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -49,7 +50,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@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -66,7 +67,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@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -79,20 +80,41 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Run Fantomas
|
- name: Run Fantomas
|
||||||
run: nix run .#fantomas -- --check .
|
run: nix run .#fantomas -- --check .
|
||||||
|
|
||||||
|
check-accurate-generations:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||||
|
- name: Install Nix
|
||||||
|
uses: cachix/install-nix-action@V27
|
||||||
|
with:
|
||||||
|
extra_nix_config: |
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Whitespace change
|
||||||
|
run: "echo ' ' >> ConsumePlugin/List.fs"
|
||||||
|
- name: Generate code
|
||||||
|
run: nix develop --command dotnet build
|
||||||
|
- name: Run Fantomas
|
||||||
|
run: nix run .#fantomas -- .
|
||||||
|
- name: Verify there is no diff
|
||||||
|
run: git diff --name-only --no-color --exit-code
|
||||||
|
|
||||||
check-nix-format:
|
check-nix-format:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -105,7 +127,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -118,7 +140,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -132,7 +154,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@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -174,8 +196,27 @@ jobs:
|
|||||||
# Verify that there is exactly one nupkg in the artifact that would be NuGet published
|
# Verify that there is exactly one nupkg in the artifact that would be NuGet published
|
||||||
run: if [[ $(find packed-attribute -maxdepth 1 -name 'WoofWare.Myriad.Plugins.Attributes.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi
|
run: if [[ $(find packed-attribute -maxdepth 1 -name 'WoofWare.Myriad.Plugins.Attributes.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi
|
||||||
|
|
||||||
|
github-release-plugin-dry-run:
|
||||||
|
needs: [nuget-pack]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
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:
|
||||||
|
DRY_RUN: 1
|
||||||
|
GITHUB_TOKEN: mock-token
|
||||||
|
run: sh .github/workflows/tag.sh
|
||||||
|
|
||||||
all-required-checks-complete:
|
all-required-checks-complete:
|
||||||
needs: [check-dotnet-format, check-nix-format, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack]
|
needs: [check-dotnet-format, check-nix-format, check-accurate-generations, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack, github-release-plugin-dry-run]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- run: echo "All required checks complete."
|
- run: echo "All required checks complete."
|
||||||
@@ -188,7 +229,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@v25
|
uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
|
109
.github/workflows/tag.sh
vendored
109
.github/workflows/tag.sh
vendored
@@ -1,6 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
find . -maxdepth 1 -type f -name '*.nupkg' -exec sh -c 'tag=$(basename "$1" .nupkg); git tag "$tag"; git push origin "$tag"' shell {} \;
|
echo "Dry-run? $DRY_RUN!"
|
||||||
|
|
||||||
|
find . -maxdepth 1 -type f ! -name "$(printf "*\n*")" -name '*.nupkg' | while IFS= read -r file
|
||||||
|
do
|
||||||
|
tag=$(basename "$file" .nupkg)
|
||||||
|
git tag "$tag"
|
||||||
|
${DRY_RUN:+echo} git push origin "$tag"
|
||||||
|
done
|
||||||
|
|
||||||
export TAG
|
export TAG
|
||||||
TAG=$(find . -maxdepth 1 -type f -name 'WoofWare.Myriad.Plugins.*.nupkg' -exec sh -c 'basename "$1" .nupkg' shell {} \; | grep -v Attributes)
|
TAG=$(find . -maxdepth 1 -type f -name 'WoofWare.Myriad.Plugins.*.nupkg' -exec sh -c 'basename "$1" .nupkg' shell {} \; | grep -v Attributes)
|
||||||
@@ -14,4 +21,100 @@ case "$TAG" in
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
# target_commitish empty indicates the repo default branch
|
# 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}'
|
curl_body='{"tag_name":"'"$TAG"'","target_commitish":"","name":"'"$TAG"'","draft":false,"prerelease":false,"generate_release_notes":false}'
|
||||||
|
|
||||||
|
echo "cURL body: $curl_body"
|
||||||
|
|
||||||
|
failed_output=$(cat <<'EOF'
|
||||||
|
{
|
||||||
|
"message": "Validation Failed",
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"resource": "Release",
|
||||||
|
"code": "already_exists",
|
||||||
|
"field": "tag_name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"documentation_url": "https://docs.github.com/rest/releases/releases#create-a-release"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
success_output=$(cat <<'EOF'
|
||||||
|
{
|
||||||
|
"url": "https://api.github.com/repos/Smaug123/WoofWare.Myriad/releases/158152116",
|
||||||
|
"assets_url": "https://api.github.com/repos/Smaug123/WoofWare.Myriad/releases/158152116/assets",
|
||||||
|
"upload_url": "https://uploads.github.com/repos/Smaug123/WoofWare.Myriad/releases/158152116/assets{?name,label}",
|
||||||
|
"html_url": "https://github.com/Smaug123/WoofWare.Myriad/releases/tag/WoofWare.Myriad.Plugins.2.1.30",
|
||||||
|
"id": 158152116,
|
||||||
|
"author": {
|
||||||
|
"login": "github-actions[bot]",
|
||||||
|
"id": 41898282,
|
||||||
|
"node_id": "MDM6Qm90NDE4OTgyODI=",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/github-actions%5Bbot%5D",
|
||||||
|
"html_url": "https://github.com/apps/github-actions",
|
||||||
|
"followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
|
||||||
|
"following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
|
||||||
|
"events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
|
||||||
|
"type": "Bot",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"node_id": "RE_kwDOJfksgc4JbTW0",
|
||||||
|
"tag_name": "WoofWare.Myriad.Plugins.2.1.30",
|
||||||
|
"target_commitish": "main",
|
||||||
|
"name": "WoofWare.Myriad.Plugins.2.1.30",
|
||||||
|
"draft": false,
|
||||||
|
"prerelease": false,
|
||||||
|
"created_at": "2024-05-30T11:00:55Z",
|
||||||
|
"published_at": "2024-05-30T11:03:02Z",
|
||||||
|
"assets": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"tarball_url": "https://api.github.com/repos/Smaug123/WoofWare.Myriad/tarball/WoofWare.Myriad.Plugins.2.1.30",
|
||||||
|
"zipball_url": "https://api.github.com/repos/Smaug123/WoofWare.Myriad/zipball/WoofWare.Myriad.Plugins.2.1.30",
|
||||||
|
"body": null
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
HANDLE_OUTPUT=''
|
||||||
|
handle_error() {
|
||||||
|
ERROR_OUTPUT="$1"
|
||||||
|
exit_message=$(echo "$ERROR_OUTPUT" | jq -r --exit-status 'if .errors | length == 1 then .errors[0].code else null end')
|
||||||
|
if [ "$exit_message" = "already_exists" ] ; then
|
||||||
|
HANDLE_OUTPUT="Did not create GitHub release because it already exists at this version."
|
||||||
|
else
|
||||||
|
echo "Unexpected error output from curl: $(cat curl_output.json)"
|
||||||
|
echo "JQ output: $(exit_message)"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_tests() {
|
||||||
|
handle_error "$failed_output"
|
||||||
|
if [ "$HANDLE_OUTPUT" != "Did not create GitHub release because it already exists at this version." ]; then
|
||||||
|
echo "Bad output from handler: $HANDLE_OUTPUT"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
HANDLE_OUTPUT=''
|
||||||
|
echo "Tests passed."
|
||||||
|
}
|
||||||
|
|
||||||
|
run_tests
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" != 1 ] ; then
|
||||||
|
if curl --fail-with-body -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 "$curl_body" > curl_output.json; then
|
||||||
|
echo "Curl succeeded."
|
||||||
|
else
|
||||||
|
handle_error "$(cat curl_output.json)"
|
||||||
|
echo "$HANDLE_OUTPUT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,6 +1,27 @@
|
|||||||
Notable changes are recorded here.
|
Notable changes are recorded here.
|
||||||
|
|
||||||
# WoofWare.Myriad.Plugins 1.4 -> 2.0
|
# WoofWare.Myriad.Plugins 2.1.33
|
||||||
|
|
||||||
|
`JsonParse` can now deserialize the discriminated unions which `JsonSerialize` wrote out.
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 2.1.32, WoofWare.Myriad.Plugins.Attributes 3.1.4
|
||||||
|
|
||||||
|
`JsonSerialize` can now serialize many discriminated unions.
|
||||||
|
(This operation is inherently opinionated, because JSON does not model discriminated unions.)
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 2.1.20, WoofWare.Myriad.Plugins.Attributes 3.0.1
|
||||||
|
|
||||||
|
We now bundle copies of the RestEase attributes in `WoofWare.Myriad.Plugins.Attributes`, in case you don't want to take a dependency on RestEase.
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 2.1.15
|
||||||
|
|
||||||
|
The `GenerateMock` generator now permits a limited amount of inheritance in the record we're mocking out (specifically, `IDisposable`).
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 2.1.8
|
||||||
|
|
||||||
|
No change to the packages, but this is when we started creating and tagging GitHub releases, which are a better source of truth than this file.
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 2.0
|
||||||
|
|
||||||
This transition split the attributes (e.g. `[<JsonParseAttribute>]`) into their own assembly, WoofWare.Myriad.Plugins.Attributes.
|
This transition split the attributes (e.g. `[<JsonParseAttribute>]`) into their own assembly, WoofWare.Myriad.Plugins.Attributes.
|
||||||
The new assembly has minimal dependencies, so you may safely use it from your own code.
|
The new assembly has minimal dependencies, so you may safely use it from your own code.
|
||||||
|
@@ -92,13 +92,13 @@ module TreeCata =
|
|||||||
let arg0_0 = treeStack.[treeStack.Count - 1]
|
let arg0_0 = treeStack.[treeStack.Count - 1]
|
||||||
treeStack.RemoveAt (treeStack.Count - 1)
|
treeStack.RemoveAt (treeStack.Count - 1)
|
||||||
cata.TreeBuilder.Parent arg0_0 |> treeBuilderStack.Add
|
cata.TreeBuilder.Parent arg0_0 |> treeBuilderStack.Add
|
||||||
| Instruction.Tree_Pair (arg2_0) ->
|
| Instruction.Tree_Pair arg2_0 ->
|
||||||
let arg0_0 = treeStack.[treeStack.Count - 1]
|
let arg0_0 = treeStack.[treeStack.Count - 1]
|
||||||
treeStack.RemoveAt (treeStack.Count - 1)
|
treeStack.RemoveAt (treeStack.Count - 1)
|
||||||
let arg1_0 = treeStack.[treeStack.Count - 1]
|
let arg1_0 = treeStack.[treeStack.Count - 1]
|
||||||
treeStack.RemoveAt (treeStack.Count - 1)
|
treeStack.RemoveAt (treeStack.Count - 1)
|
||||||
cata.Tree.Pair arg0_0 arg1_0 arg2_0 |> treeStack.Add
|
cata.Tree.Pair arg0_0 arg1_0 arg2_0 |> treeStack.Add
|
||||||
| Instruction.Tree_Sequential (arg0_0) ->
|
| Instruction.Tree_Sequential arg0_0 ->
|
||||||
let arg0_0_len = arg0_0
|
let arg0_0_len = arg0_0
|
||||||
|
|
||||||
let arg0_0 =
|
let arg0_0 =
|
||||||
|
@@ -129,7 +129,7 @@ module GiftCata =
|
|||||||
| Gift.WithACard (arg0_0, message) ->
|
| Gift.WithACard (arg0_0, message) ->
|
||||||
instructions.Add (Instruction.Gift_WithACard (message))
|
instructions.Add (Instruction.Gift_WithACard (message))
|
||||||
instructions.Add (Instruction.Process__Gift arg0_0)
|
instructions.Add (Instruction.Process__Gift arg0_0)
|
||||||
| Instruction.Gift_Wrapped (arg1_0) ->
|
| Instruction.Gift_Wrapped arg1_0 ->
|
||||||
let arg0_0 = giftStack.[giftStack.Count - 1]
|
let arg0_0 = giftStack.[giftStack.Count - 1]
|
||||||
giftStack.RemoveAt (giftStack.Count - 1)
|
giftStack.RemoveAt (giftStack.Count - 1)
|
||||||
cata.Gift.Wrapped arg0_0 arg1_0 |> giftStack.Add
|
cata.Gift.Wrapped arg0_0 arg1_0 |> giftStack.Add
|
||||||
@@ -137,7 +137,7 @@ module GiftCata =
|
|||||||
let arg0_0 = giftStack.[giftStack.Count - 1]
|
let arg0_0 = giftStack.[giftStack.Count - 1]
|
||||||
giftStack.RemoveAt (giftStack.Count - 1)
|
giftStack.RemoveAt (giftStack.Count - 1)
|
||||||
cata.Gift.Boxed arg0_0 |> giftStack.Add
|
cata.Gift.Boxed arg0_0 |> giftStack.Add
|
||||||
| Instruction.Gift_WithACard (message) ->
|
| Instruction.Gift_WithACard message ->
|
||||||
let arg0_0 = giftStack.[giftStack.Count - 1]
|
let arg0_0 = giftStack.[giftStack.Count - 1]
|
||||||
giftStack.RemoveAt (giftStack.Count - 1)
|
giftStack.RemoveAt (giftStack.Count - 1)
|
||||||
cata.Gift.WithACard arg0_0 message |> giftStack.Add
|
cata.Gift.WithACard arg0_0 message |> giftStack.Add
|
||||||
|
@@ -4,16 +4,42 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System.Text.Json.Serialization
|
||||||
|
|
||||||
|
/// Module containing JSON serializing methods for the InternalTypeNotExtensionSerial type
|
||||||
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
|
module internal InternalTypeNotExtensionSerial =
|
||||||
|
/// Serialize to a JSON node
|
||||||
|
let toJsonNode (input : InternalTypeNotExtensionSerial) : System.Text.Json.Nodes.JsonNode =
|
||||||
|
let node = System.Text.Json.Nodes.JsonObject ()
|
||||||
|
do node.Add ((Literals.something), System.Text.Json.Nodes.JsonValue.Create<string> input.InternalThing2)
|
||||||
|
node :> _
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System.Text.Json.Serialization
|
||||||
|
|
||||||
|
/// Module containing JSON serializing extension members for the InternalTypeExtension type
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal InternalTypeExtensionJsonSerializeExtension =
|
||||||
|
/// Extension methods for JSON parsing
|
||||||
|
type InternalTypeExtension with
|
||||||
|
|
||||||
|
/// Serialize to a JSON node
|
||||||
|
static member toJsonNode (input : InternalTypeExtension) : System.Text.Json.Nodes.JsonNode =
|
||||||
|
let node = System.Text.Json.Nodes.JsonObject ()
|
||||||
|
do node.Add ((Literals.something), System.Text.Json.Nodes.JsonValue.Create<string> input.ExternalThing)
|
||||||
|
node :> _
|
||||||
|
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the InnerType type
|
/// Module containing JSON parsing methods for the InnerType type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module InnerType =
|
module InnerType =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType =
|
||||||
let Thing =
|
let arg_0 =
|
||||||
(match node.[(Literals.something)] with
|
(match node.[(Literals.something)] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -26,17 +52,16 @@ module InnerType =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Thing = Thing
|
Thing = arg_0
|
||||||
}
|
}
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JsonRecordType type
|
/// Module containing JSON parsing methods for the JsonRecordType type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JsonRecordType =
|
module JsonRecordType =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType =
|
||||||
let F =
|
let arg_5 =
|
||||||
(match node.["f"] with
|
(match node.["f"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -49,7 +74,7 @@ module JsonRecordType =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
||||||
|> Array.ofSeq
|
|> Array.ofSeq
|
||||||
|
|
||||||
let E =
|
let arg_4 =
|
||||||
(match node.["e"] with
|
(match node.["e"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -62,7 +87,7 @@ module JsonRecordType =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
||||||
|> Array.ofSeq
|
|> Array.ofSeq
|
||||||
|
|
||||||
let D =
|
let arg_3 =
|
||||||
InnerType.jsonParse (
|
InnerType.jsonParse (
|
||||||
match node.["d"] with
|
match node.["d"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -74,7 +99,7 @@ module JsonRecordType =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let C =
|
let arg_2 =
|
||||||
(match node.["hi"] with
|
(match node.["hi"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -87,7 +112,7 @@ module JsonRecordType =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let B =
|
let arg_1 =
|
||||||
(match node.["another-thing"] with
|
(match node.["another-thing"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -99,7 +124,7 @@ module JsonRecordType =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let A =
|
let arg_0 =
|
||||||
(match node.["a"] with
|
(match node.["a"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -112,15 +137,62 @@ module JsonRecordType =
|
|||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
A = A
|
A = arg_0
|
||||||
B = B
|
B = arg_1
|
||||||
C = C
|
C = arg_2
|
||||||
D = D
|
D = arg_3
|
||||||
E = E
|
E = arg_4
|
||||||
F = F
|
F = arg_5
|
||||||
}
|
}
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
/// Module containing JSON parsing methods for the InternalTypeNotExtension type
|
||||||
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
|
module internal InternalTypeNotExtension =
|
||||||
|
/// Parse from a JSON node.
|
||||||
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InternalTypeNotExtension =
|
||||||
|
let arg_0 =
|
||||||
|
(match node.[(Literals.something)] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ((Literals.something))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<string> ()
|
||||||
|
|
||||||
|
{
|
||||||
|
InternalThing = arg_0
|
||||||
|
}
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
/// Module containing JSON parsing extension members for the InternalTypeExtension type
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal InternalTypeExtensionJsonParseExtension =
|
||||||
|
/// Extension methods for JSON parsing
|
||||||
|
type InternalTypeExtension with
|
||||||
|
|
||||||
|
/// Parse from a JSON node.
|
||||||
|
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : InternalTypeExtension =
|
||||||
|
let arg_0 =
|
||||||
|
(match node.[(Literals.something)] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ((Literals.something))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<string> ()
|
||||||
|
|
||||||
|
{
|
||||||
|
ExternalThing = arg_0
|
||||||
|
}
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing extension members for the ToGetExtensionMethod type
|
/// Module containing JSON parsing extension members for the ToGetExtensionMethod type
|
||||||
[<AutoOpen>]
|
[<AutoOpen>]
|
||||||
module ToGetExtensionMethodJsonParseExtension =
|
module ToGetExtensionMethodJsonParseExtension =
|
||||||
@@ -129,24 +201,230 @@ module ToGetExtensionMethodJsonParseExtension =
|
|||||||
|
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : ToGetExtensionMethod =
|
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : ToGetExtensionMethod =
|
||||||
let Sailor =
|
let arg_20 = System.Numerics.BigInteger.Parse (node.["whiskey"].ToJsonString ())
|
||||||
(match node.["sailor"] with
|
|
||||||
|
let arg_19 =
|
||||||
|
(match node.["victor"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
System.Collections.Generic.KeyNotFoundException (
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
sprintf "Required key '%s' not found on JSON object" ("sailor")
|
sprintf "Required key '%s' not found on JSON object" ("victor")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Char> ()
|
||||||
|
|
||||||
|
let arg_18 =
|
||||||
|
(match node.["uniform"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("uniform")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Decimal> ()
|
||||||
|
|
||||||
|
let arg_17 =
|
||||||
|
(match node.["tango"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("tango")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.SByte> ()
|
||||||
|
|
||||||
|
let arg_16 =
|
||||||
|
(match node.["quebec"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("quebec")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Byte> ()
|
||||||
|
|
||||||
|
let arg_15 =
|
||||||
|
(match node.["papa"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("papa")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Byte> ()
|
||||||
|
|
||||||
|
let arg_14 =
|
||||||
|
(match node.["oscar"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("oscar")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.SByte> ()
|
||||||
|
|
||||||
|
let arg_13 =
|
||||||
|
(match node.["november"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("november")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.UInt16> ()
|
||||||
|
|
||||||
|
let arg_12 =
|
||||||
|
(match node.["mike"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("mike")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Int16> ()
|
||||||
|
|
||||||
|
let arg_11 =
|
||||||
|
(match node.["lima"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("lima")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.UInt32> ()
|
||||||
|
|
||||||
|
let arg_10 =
|
||||||
|
(match node.["kilo"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("kilo")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Int32> ()
|
||||||
|
|
||||||
|
let arg_9 =
|
||||||
|
(match node.["juliette"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("juliette")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.UInt32> ()
|
||||||
|
|
||||||
|
let arg_8 =
|
||||||
|
(match node.["india"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("india")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<int> ()
|
||||||
|
|
||||||
|
let arg_7 =
|
||||||
|
(match node.["hotel"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("hotel")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.UInt64> ()
|
||||||
|
|
||||||
|
let arg_6 =
|
||||||
|
(match node.["golf"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("golf")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Int64> ()
|
||||||
|
|
||||||
|
let arg_5 =
|
||||||
|
(match node.["foxtrot"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("foxtrot")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Double> ()
|
||||||
|
|
||||||
|
let arg_4 =
|
||||||
|
(match node.["echo"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("echo")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Single> ()
|
||||||
|
|
||||||
|
let arg_3 =
|
||||||
|
(match node.["delta"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("delta")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<System.Single> ()
|
||||||
|
|
||||||
|
let arg_2 =
|
||||||
|
(match node.["charlie"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("charlie")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
| v -> v)
|
| v -> v)
|
||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<float> ()
|
.GetValue<float> ()
|
||||||
|
|
||||||
let Soldier =
|
let arg_1 =
|
||||||
(match node.["soldier"] with
|
(match node.["bravo"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
System.Collections.Generic.KeyNotFoundException (
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
sprintf "Required key '%s' not found on JSON object" ("soldier")
|
sprintf "Required key '%s' not found on JSON object" ("bravo")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
| v -> v)
|
| v -> v)
|
||||||
@@ -154,24 +432,12 @@ module ToGetExtensionMethodJsonParseExtension =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|> System.Uri
|
|> System.Uri
|
||||||
|
|
||||||
let Tailor =
|
let arg_0 =
|
||||||
(match node.["tailor"] with
|
(match node.["alpha"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
System.Collections.Generic.KeyNotFoundException (
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
sprintf "Required key '%s' not found on JSON object" ("tailor")
|
sprintf "Required key '%s' not found on JSON object" ("alpha")
|
||||||
)
|
|
||||||
)
|
|
||||||
| v -> v)
|
|
||||||
.AsValue()
|
|
||||||
.GetValue<int> ()
|
|
||||||
|
|
||||||
let Tinker =
|
|
||||||
(match node.["tinker"] with
|
|
||||||
| null ->
|
|
||||||
raise (
|
|
||||||
System.Collections.Generic.KeyNotFoundException (
|
|
||||||
sprintf "Required key '%s' not found on JSON object" ("tinker")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
| v -> v)
|
| v -> v)
|
||||||
@@ -179,8 +445,25 @@ module ToGetExtensionMethodJsonParseExtension =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Tinker = Tinker
|
Alpha = arg_0
|
||||||
Tailor = Tailor
|
Bravo = arg_1
|
||||||
Soldier = Soldier
|
Charlie = arg_2
|
||||||
Sailor = Sailor
|
Delta = arg_3
|
||||||
|
Echo = arg_4
|
||||||
|
Foxtrot = arg_5
|
||||||
|
Golf = arg_6
|
||||||
|
Hotel = arg_7
|
||||||
|
India = arg_8
|
||||||
|
Juliette = arg_9
|
||||||
|
Kilo = arg_10
|
||||||
|
Lima = arg_11
|
||||||
|
Mike = arg_12
|
||||||
|
November = arg_13
|
||||||
|
Oscar = arg_14
|
||||||
|
Papa = arg_15
|
||||||
|
Quebec = arg_16
|
||||||
|
Tango = arg_17
|
||||||
|
Uniform = arg_18
|
||||||
|
Victor = arg_19
|
||||||
|
Whiskey = arg_20
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
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
|
||||||
@@ -18,17 +19,18 @@ type internal PublicTypeMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PublicTypeMock =
|
static member Empty : PublicTypeMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
Mem3 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -42,17 +44,18 @@ type public PublicTypeInternalFalseMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PublicTypeInternalFalseMock =
|
static member Empty : PublicTypeInternalFalseMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
Mem3 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -65,15 +68,16 @@ type internal InternalTypeMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : InternalTypeMock =
|
static member Empty : InternalTypeMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -86,15 +90,16 @@ type private PrivateTypeMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PrivateTypeMock =
|
static member Empty : PrivateTypeMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -107,15 +112,16 @@ type private PrivateTypeInternalFalseMock =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty : PrivateTypeInternalFalseMock =
|
static member Empty : PrivateTypeInternalFalseMock =
|
||||||
{
|
{
|
||||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -127,13 +133,14 @@ type internal VeryPublicTypeMock<'a, 'b> =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty () : VeryPublicTypeMock<'a, 'b> =
|
static member Empty () : VeryPublicTypeMock<'a, 'b> =
|
||||||
{
|
{
|
||||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -150,18 +157,18 @@ type internal CurriedMock<'a> =
|
|||||||
/// An implementation where every method throws.
|
/// An implementation where every method throws.
|
||||||
static member Empty () : CurriedMock<'a> =
|
static member Empty () : CurriedMock<'a> =
|
||||||
{
|
{
|
||||||
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
Mem3 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem3"))
|
||||||
Mem4 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem4"))
|
||||||
Mem5 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem5"))
|
||||||
Mem6 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem6"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@@ -171,3 +178,31 @@ 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 _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||||
|
Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ()
|
||||||
|
@@ -41,12 +41,11 @@ module MemberJsonSerializeExtension =
|
|||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymOpeningHours type
|
/// Module containing JSON parsing methods for the GymOpeningHours type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymOpeningHours =
|
module GymOpeningHours =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymOpeningHours =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymOpeningHours =
|
||||||
let OpeningHours =
|
let arg_1 =
|
||||||
(match node.["openingHours"] with
|
(match node.["openingHours"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -59,7 +58,7 @@ module GymOpeningHours =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let IsAlwaysOpen =
|
let arg_0 =
|
||||||
(match node.["isAlwaysOpen"] with
|
(match node.["isAlwaysOpen"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -72,18 +71,17 @@ module GymOpeningHours =
|
|||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
IsAlwaysOpen = IsAlwaysOpen
|
IsAlwaysOpen = arg_0
|
||||||
OpeningHours = OpeningHours
|
OpeningHours = arg_1
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymAccessOptions type
|
/// Module containing JSON parsing methods for the GymAccessOptions type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymAccessOptions =
|
module GymAccessOptions =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAccessOptions =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAccessOptions =
|
||||||
let QrCodeAccess =
|
let arg_1 =
|
||||||
(match node.["qrCodeAccess"] with
|
(match node.["qrCodeAccess"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -95,7 +93,7 @@ module GymAccessOptions =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
let PinAccess =
|
let arg_0 =
|
||||||
(match node.["pinAccess"] with
|
(match node.["pinAccess"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -108,18 +106,17 @@ module GymAccessOptions =
|
|||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
PinAccess = PinAccess
|
PinAccess = arg_0
|
||||||
QrCodeAccess = QrCodeAccess
|
QrCodeAccess = arg_1
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymLocation type
|
/// Module containing JSON parsing methods for the GymLocation type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymLocation =
|
module GymLocation =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymLocation =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymLocation =
|
||||||
let Latitude =
|
let arg_1 =
|
||||||
try
|
try
|
||||||
(match node.["latitude"] with
|
(match node.["latitude"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -152,7 +149,7 @@ module GymLocation =
|
|||||||
else
|
else
|
||||||
reraise ()
|
reraise ()
|
||||||
|
|
||||||
let Longitude =
|
let arg_0 =
|
||||||
try
|
try
|
||||||
(match node.["longitude"] with
|
(match node.["longitude"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -186,18 +183,17 @@ module GymLocation =
|
|||||||
reraise ()
|
reraise ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Longitude = Longitude
|
Longitude = arg_0
|
||||||
Latitude = Latitude
|
Latitude = arg_1
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymAddress type
|
/// Module containing JSON parsing methods for the GymAddress type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymAddress =
|
module GymAddress =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAddress =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAddress =
|
||||||
let Postcode =
|
let arg_5 =
|
||||||
(match node.["postcode"] with
|
(match node.["postcode"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -209,12 +205,12 @@ module GymAddress =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let County =
|
let arg_4 =
|
||||||
match node.["county"] with
|
match node.["county"] with
|
||||||
| null -> None
|
| null -> None
|
||||||
| v -> v.AsValue().GetValue<string> () |> Some
|
| v -> v.AsValue().GetValue<string> () |> Some
|
||||||
|
|
||||||
let Town =
|
let arg_3 =
|
||||||
(match node.["town"] with
|
(match node.["town"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -226,17 +222,17 @@ module GymAddress =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let AddressLine3 =
|
let arg_2 =
|
||||||
match node.["addressLine3"] with
|
match node.["addressLine3"] with
|
||||||
| null -> None
|
| null -> None
|
||||||
| v -> v.AsValue().GetValue<string> () |> Some
|
| v -> v.AsValue().GetValue<string> () |> Some
|
||||||
|
|
||||||
let AddressLine2 =
|
let arg_1 =
|
||||||
match node.["addressLine2"] with
|
match node.["addressLine2"] with
|
||||||
| null -> None
|
| null -> None
|
||||||
| v -> v.AsValue().GetValue<string> () |> Some
|
| v -> v.AsValue().GetValue<string> () |> Some
|
||||||
|
|
||||||
let AddressLine1 =
|
let arg_0 =
|
||||||
(match node.["addressLine1"] with
|
(match node.["addressLine1"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -249,22 +245,21 @@ module GymAddress =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
AddressLine1 = AddressLine1
|
AddressLine1 = arg_0
|
||||||
AddressLine2 = AddressLine2
|
AddressLine2 = arg_1
|
||||||
AddressLine3 = AddressLine3
|
AddressLine3 = arg_2
|
||||||
Town = Town
|
Town = arg_3
|
||||||
County = County
|
County = arg_4
|
||||||
Postcode = Postcode
|
Postcode = arg_5
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the Gym type
|
/// Module containing JSON parsing methods for the Gym type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module Gym =
|
module Gym =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Gym =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Gym =
|
||||||
let ReopenDate =
|
let arg_10 =
|
||||||
(match node.["reopenDate"] with
|
(match node.["reopenDate"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -276,7 +271,7 @@ module Gym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let TimeZone =
|
let arg_9 =
|
||||||
(match node.["timeZone"] with
|
(match node.["timeZone"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -288,7 +283,7 @@ module Gym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let Location =
|
let arg_8 =
|
||||||
GymLocation.jsonParse (
|
GymLocation.jsonParse (
|
||||||
match node.["location"] with
|
match node.["location"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -300,7 +295,7 @@ module Gym =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let AccessOptions =
|
let arg_7 =
|
||||||
GymAccessOptions.jsonParse (
|
GymAccessOptions.jsonParse (
|
||||||
match node.["accessOptions"] with
|
match node.["accessOptions"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -312,7 +307,7 @@ module Gym =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let GymOpeningHours =
|
let arg_6 =
|
||||||
GymOpeningHours.jsonParse (
|
GymOpeningHours.jsonParse (
|
||||||
match node.["gymOpeningHours"] with
|
match node.["gymOpeningHours"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -324,7 +319,7 @@ module Gym =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let EmailAddress =
|
let arg_5 =
|
||||||
(match node.["emailAddress"] with
|
(match node.["emailAddress"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -336,7 +331,7 @@ module Gym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let PhoneNumber =
|
let arg_4 =
|
||||||
(match node.["phoneNumber"] with
|
(match node.["phoneNumber"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -348,7 +343,7 @@ module Gym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let Address =
|
let arg_3 =
|
||||||
GymAddress.jsonParse (
|
GymAddress.jsonParse (
|
||||||
match node.["address"] with
|
match node.["address"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -360,7 +355,7 @@ module Gym =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let Status =
|
let arg_2 =
|
||||||
(match node.["status"] with
|
(match node.["status"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -372,7 +367,7 @@ module Gym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Id =
|
let arg_1 =
|
||||||
(match node.["id"] with
|
(match node.["id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -384,7 +379,7 @@ module Gym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Name =
|
let arg_0 =
|
||||||
(match node.["name"] with
|
(match node.["name"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -397,17 +392,17 @@ module Gym =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Name = Name
|
Name = arg_0
|
||||||
Id = Id
|
Id = arg_1
|
||||||
Status = Status
|
Status = arg_2
|
||||||
Address = Address
|
Address = arg_3
|
||||||
PhoneNumber = PhoneNumber
|
PhoneNumber = arg_4
|
||||||
EmailAddress = EmailAddress
|
EmailAddress = arg_5
|
||||||
GymOpeningHours = GymOpeningHours
|
GymOpeningHours = arg_6
|
||||||
AccessOptions = AccessOptions
|
AccessOptions = arg_7
|
||||||
Location = Location
|
Location = arg_8
|
||||||
TimeZone = TimeZone
|
TimeZone = arg_9
|
||||||
ReopenDate = ReopenDate
|
ReopenDate = arg_10
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
@@ -419,7 +414,7 @@ module MemberJsonParseExtension =
|
|||||||
|
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : Member =
|
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : Member =
|
||||||
let MemberStatus =
|
let arg_14 =
|
||||||
(match node.["memberStatus"] with
|
(match node.["memberStatus"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -431,7 +426,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let SuspendedReason =
|
let arg_13 =
|
||||||
(match node.["suspendedReason"] with
|
(match node.["suspendedReason"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -443,7 +438,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let MembershipLevel =
|
let arg_12 =
|
||||||
(match node.["membershipLevel"] with
|
(match node.["membershipLevel"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -455,7 +450,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let MembershipName =
|
let arg_11 =
|
||||||
(match node.["membershipName"] with
|
(match node.["membershipName"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -467,7 +462,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let Postcode =
|
let arg_10 =
|
||||||
(match node.["postCode"] with
|
(match node.["postCode"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -479,7 +474,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let MobileNumber =
|
let arg_9 =
|
||||||
(match node.["mobileNumber"] with
|
(match node.["mobileNumber"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -491,7 +486,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let DateOfBirth =
|
let arg_8 =
|
||||||
(match node.["dateofBirth"] with
|
(match node.["dateofBirth"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -504,7 +499,7 @@ module MemberJsonParseExtension =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|> System.DateOnly.Parse
|
|> System.DateOnly.Parse
|
||||||
|
|
||||||
let GymAccessPin =
|
let arg_7 =
|
||||||
(match node.["gymAccessPin"] with
|
(match node.["gymAccessPin"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -516,7 +511,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let EmailAddress =
|
let arg_6 =
|
||||||
(match node.["emailAddress"] with
|
(match node.["emailAddress"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -528,7 +523,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let HomeGymName =
|
let arg_5 =
|
||||||
(match node.["homeGymName"] with
|
(match node.["homeGymName"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -540,7 +535,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let HomeGymId =
|
let arg_4 =
|
||||||
(match node.["homeGymId"] with
|
(match node.["homeGymId"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -552,7 +547,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let LastName =
|
let arg_3 =
|
||||||
(match node.["lastName"] with
|
(match node.["lastName"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -564,7 +559,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let FirstName =
|
let arg_2 =
|
||||||
(match node.["firstName"] with
|
(match node.["firstName"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -576,7 +571,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let CompoundMemberId =
|
let arg_1 =
|
||||||
(match node.["compoundMemberId"] with
|
(match node.["compoundMemberId"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -588,7 +583,7 @@ module MemberJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let Id =
|
let arg_0 =
|
||||||
(match node.["id"] with
|
(match node.["id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -601,31 +596,30 @@ module MemberJsonParseExtension =
|
|||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Id = Id
|
Id = arg_0
|
||||||
CompoundMemberId = CompoundMemberId
|
CompoundMemberId = arg_1
|
||||||
FirstName = FirstName
|
FirstName = arg_2
|
||||||
LastName = LastName
|
LastName = arg_3
|
||||||
HomeGymId = HomeGymId
|
HomeGymId = arg_4
|
||||||
HomeGymName = HomeGymName
|
HomeGymName = arg_5
|
||||||
EmailAddress = EmailAddress
|
EmailAddress = arg_6
|
||||||
GymAccessPin = GymAccessPin
|
GymAccessPin = arg_7
|
||||||
DateOfBirth = DateOfBirth
|
DateOfBirth = arg_8
|
||||||
MobileNumber = MobileNumber
|
MobileNumber = arg_9
|
||||||
Postcode = Postcode
|
Postcode = arg_10
|
||||||
MembershipName = MembershipName
|
MembershipName = arg_11
|
||||||
MembershipLevel = MembershipLevel
|
MembershipLevel = arg_12
|
||||||
SuspendedReason = SuspendedReason
|
SuspendedReason = arg_13
|
||||||
MemberStatus = MemberStatus
|
MemberStatus = arg_14
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the GymAttendance type
|
/// Module containing JSON parsing methods for the GymAttendance type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module GymAttendance =
|
module GymAttendance =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAttendance =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAttendance =
|
||||||
let MaximumCapacity =
|
let arg_8 =
|
||||||
(match node.["maximumCapacity"] with
|
(match node.["maximumCapacity"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -637,7 +631,7 @@ module GymAttendance =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let LastRefreshedPeopleInClasses =
|
let arg_7 =
|
||||||
(match node.["lastRefreshedPeopleInClasses"] with
|
(match node.["lastRefreshedPeopleInClasses"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -650,7 +644,7 @@ module GymAttendance =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|> System.DateTime.Parse
|
|> System.DateTime.Parse
|
||||||
|
|
||||||
let LastRefreshed =
|
let arg_6 =
|
||||||
(match node.["lastRefreshed"] with
|
(match node.["lastRefreshed"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -663,7 +657,7 @@ module GymAttendance =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|> System.DateTime.Parse
|
|> System.DateTime.Parse
|
||||||
|
|
||||||
let AttendanceTime =
|
let arg_5 =
|
||||||
(match node.["attendanceTime"] with
|
(match node.["attendanceTime"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -676,7 +670,7 @@ module GymAttendance =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|> System.DateTime.Parse
|
|> System.DateTime.Parse
|
||||||
|
|
||||||
let IsApproximate =
|
let arg_4 =
|
||||||
(match node.["isApproximate"] with
|
(match node.["isApproximate"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -688,12 +682,12 @@ module GymAttendance =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
let TotalPeopleSuffix =
|
let arg_3 =
|
||||||
match node.["totalPeopleSuffix"] with
|
match node.["totalPeopleSuffix"] with
|
||||||
| null -> None
|
| null -> None
|
||||||
| v -> v.AsValue().GetValue<string> () |> Some
|
| v -> v.AsValue().GetValue<string> () |> Some
|
||||||
|
|
||||||
let TotalPeopleInClasses =
|
let arg_2 =
|
||||||
(match node.["totalPeopleInClasses"] with
|
(match node.["totalPeopleInClasses"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -705,7 +699,7 @@ module GymAttendance =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let TotalPeopleInGym =
|
let arg_1 =
|
||||||
(match node.["totalPeopleInGym"] with
|
(match node.["totalPeopleInGym"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -717,7 +711,7 @@ module GymAttendance =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Description =
|
let arg_0 =
|
||||||
(match node.["description"] with
|
(match node.["description"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -730,25 +724,24 @@ module GymAttendance =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Description = Description
|
Description = arg_0
|
||||||
TotalPeopleInGym = TotalPeopleInGym
|
TotalPeopleInGym = arg_1
|
||||||
TotalPeopleInClasses = TotalPeopleInClasses
|
TotalPeopleInClasses = arg_2
|
||||||
TotalPeopleSuffix = TotalPeopleSuffix
|
TotalPeopleSuffix = arg_3
|
||||||
IsApproximate = IsApproximate
|
IsApproximate = arg_4
|
||||||
AttendanceTime = AttendanceTime
|
AttendanceTime = arg_5
|
||||||
LastRefreshed = LastRefreshed
|
LastRefreshed = arg_6
|
||||||
LastRefreshedPeopleInClasses = LastRefreshedPeopleInClasses
|
LastRefreshedPeopleInClasses = arg_7
|
||||||
MaximumCapacity = MaximumCapacity
|
MaximumCapacity = arg_8
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the MemberActivityDto type
|
/// Module containing JSON parsing methods for the MemberActivityDto type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module MemberActivityDto =
|
module MemberActivityDto =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : MemberActivityDto =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : MemberActivityDto =
|
||||||
let LastRefreshed =
|
let arg_5 =
|
||||||
(match node.["lastRefreshed"] with
|
(match node.["lastRefreshed"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -761,7 +754,7 @@ module MemberActivityDto =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|> System.DateTime.Parse
|
|> System.DateTime.Parse
|
||||||
|
|
||||||
let IsEstimated =
|
let arg_4 =
|
||||||
(match node.["isEstimated"] with
|
(match node.["isEstimated"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -773,7 +766,7 @@ module MemberActivityDto =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
let TotalClasses =
|
let arg_3 =
|
||||||
(match node.["totalClasses"] with
|
(match node.["totalClasses"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -785,7 +778,7 @@ module MemberActivityDto =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let TotalVisits =
|
let arg_2 =
|
||||||
(match node.["totalVisits"] with
|
(match node.["totalVisits"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -797,7 +790,7 @@ module MemberActivityDto =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let AverageDuration =
|
let arg_1 =
|
||||||
(match node.["averageDuration"] with
|
(match node.["averageDuration"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -809,7 +802,7 @@ module MemberActivityDto =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let TotalDuration =
|
let arg_0 =
|
||||||
(match node.["totalDuration"] with
|
(match node.["totalDuration"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -822,22 +815,21 @@ module MemberActivityDto =
|
|||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
TotalDuration = TotalDuration
|
TotalDuration = arg_0
|
||||||
AverageDuration = AverageDuration
|
AverageDuration = arg_1
|
||||||
TotalVisits = TotalVisits
|
TotalVisits = arg_2
|
||||||
TotalClasses = TotalClasses
|
TotalClasses = arg_3
|
||||||
IsEstimated = IsEstimated
|
IsEstimated = arg_4
|
||||||
LastRefreshed = LastRefreshed
|
LastRefreshed = arg_5
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the SessionsAggregate type
|
/// Module containing JSON parsing methods for the SessionsAggregate type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module SessionsAggregate =
|
module SessionsAggregate =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
|
||||||
let Duration =
|
let arg_2 =
|
||||||
(match node.["Duration"] with
|
(match node.["Duration"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -849,7 +841,7 @@ module SessionsAggregate =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Visits =
|
let arg_1 =
|
||||||
(match node.["Visits"] with
|
(match node.["Visits"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -861,7 +853,7 @@ module SessionsAggregate =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Activities =
|
let arg_0 =
|
||||||
(match node.["Activities"] with
|
(match node.["Activities"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -874,19 +866,18 @@ module SessionsAggregate =
|
|||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Activities = Activities
|
Activities = arg_0
|
||||||
Visits = Visits
|
Visits = arg_1
|
||||||
Duration = Duration
|
Duration = arg_2
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the VisitGym type
|
/// Module containing JSON parsing methods for the VisitGym type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module VisitGym =
|
module VisitGym =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
|
||||||
let Status =
|
let arg_2 =
|
||||||
(match node.["Status"] with
|
(match node.["Status"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -898,7 +889,7 @@ module VisitGym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let Name =
|
let arg_1 =
|
||||||
(match node.["Name"] with
|
(match node.["Name"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -910,7 +901,7 @@ module VisitGym =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let Id =
|
let arg_0 =
|
||||||
(match node.["Id"] with
|
(match node.["Id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -923,19 +914,18 @@ module VisitGym =
|
|||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Id = Id
|
Id = arg_0
|
||||||
Name = Name
|
Name = arg_1
|
||||||
Status = Status
|
Status = arg_2
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the Visit type
|
/// Module containing JSON parsing methods for the Visit type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module Visit =
|
module Visit =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
|
||||||
let Gym =
|
let arg_3 =
|
||||||
VisitGym.jsonParse (
|
VisitGym.jsonParse (
|
||||||
match node.["Gym"] with
|
match node.["Gym"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -947,7 +937,7 @@ module Visit =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let Duration =
|
let arg_2 =
|
||||||
(match node.["Duration"] with
|
(match node.["Duration"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -959,7 +949,7 @@ module Visit =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let StartTime =
|
let arg_1 =
|
||||||
(match node.["StartTime"] with
|
(match node.["StartTime"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -972,7 +962,7 @@ module Visit =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|> System.DateTime.Parse
|
|> System.DateTime.Parse
|
||||||
|
|
||||||
let IsDurationEstimated =
|
let arg_0 =
|
||||||
(match node.["IsDurationEstimated"] with
|
(match node.["IsDurationEstimated"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -985,20 +975,19 @@ module Visit =
|
|||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
IsDurationEstimated = IsDurationEstimated
|
IsDurationEstimated = arg_0
|
||||||
StartTime = StartTime
|
StartTime = arg_1
|
||||||
Duration = Duration
|
Duration = arg_2
|
||||||
Gym = Gym
|
Gym = arg_3
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the SessionsSummary type
|
/// Module containing JSON parsing methods for the SessionsSummary type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module SessionsSummary =
|
module SessionsSummary =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
|
||||||
let ThisWeek =
|
let arg_1 =
|
||||||
SessionsAggregate.jsonParse (
|
SessionsAggregate.jsonParse (
|
||||||
match node.["ThisWeek"] with
|
match node.["ThisWeek"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -1010,7 +999,7 @@ module SessionsSummary =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let Total =
|
let arg_0 =
|
||||||
SessionsAggregate.jsonParse (
|
SessionsAggregate.jsonParse (
|
||||||
match node.["Total"] with
|
match node.["Total"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -1023,18 +1012,17 @@ module SessionsSummary =
|
|||||||
)
|
)
|
||||||
|
|
||||||
{
|
{
|
||||||
Total = Total
|
Total = arg_0
|
||||||
ThisWeek = ThisWeek
|
ThisWeek = arg_1
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the Sessions type
|
/// Module containing JSON parsing methods for the Sessions type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module Sessions =
|
module Sessions =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
|
||||||
let Visits =
|
let arg_1 =
|
||||||
(match node.["Visits"] with
|
(match node.["Visits"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -1047,7 +1035,7 @@ module Sessions =
|
|||||||
|> Seq.map (fun elt -> Visit.jsonParse elt)
|
|> Seq.map (fun elt -> Visit.jsonParse elt)
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let Summary =
|
let arg_0 =
|
||||||
SessionsSummary.jsonParse (
|
SessionsSummary.jsonParse (
|
||||||
match node.["Summary"] with
|
match node.["Summary"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -1060,18 +1048,17 @@ module Sessions =
|
|||||||
)
|
)
|
||||||
|
|
||||||
{
|
{
|
||||||
Summary = Summary
|
Summary = arg_0
|
||||||
Visits = Visits
|
Visits = arg_1
|
||||||
}
|
}
|
||||||
namespace PureGym
|
namespace PureGym
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the UriThing type
|
/// Module containing JSON parsing methods for the UriThing type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module UriThing =
|
module UriThing =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing =
|
||||||
let SomeUri =
|
let arg_0 =
|
||||||
(match node.["someUri"] with
|
(match node.["someUri"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -1085,5 +1072,5 @@ module UriThing =
|
|||||||
|> System.Uri
|
|> System.Uri
|
||||||
|
|
||||||
{
|
{
|
||||||
SomeUri = SomeUri
|
SomeUri = arg_0
|
||||||
}
|
}
|
||||||
|
@@ -17,8 +17,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module PureGymApi =
|
module PureGymApi =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IPureGymApi =
|
let make (client : System.Net.Http.HttpClient) : IPureGymApi =
|
||||||
@@ -87,6 +86,40 @@ module PureGymApi =
|
|||||||
}
|
}
|
||||||
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
|
||||||
|
member _.GetGymAttendance' (gymId : int, 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 (
|
||||||
|
"v1/gyms/{gym_id}/attendance"
|
||||||
|
.Replace ("{gym_id}", gymId.ToString () |> 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 GymAttendance.jsonParse jsonNode
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
|
||||||
member _.GetMember (ct : CancellationToken option) =
|
member _.GetMember (ct : CancellationToken option) =
|
||||||
async {
|
async {
|
||||||
let! ct = Async.CancellationToken
|
let! ct = Async.CancellationToken
|
||||||
@@ -288,7 +321,52 @@ module PureGymApi =
|
|||||||
| v -> v),
|
| v -> v),
|
||||||
System.Uri (
|
System.Uri (
|
||||||
("/v2/gymSessions/member"
|
("/v2/gymSessions/member"
|
||||||
+ "?fromDate="
|
+ (if "/v2/gymSessions/member".IndexOf (char 63) >= 0 then
|
||||||
|
"&"
|
||||||
|
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)),
|
||||||
@@ -976,8 +1054,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module internal ApiWithoutBaseAddress =
|
module internal ApiWithoutBaseAddress =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IApiWithoutBaseAddress =
|
let make (client : System.Net.Http.HttpClient) : IApiWithoutBaseAddress =
|
||||||
@@ -1028,8 +1105,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module ApiWithBasePath =
|
module ApiWithBasePath =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IApiWithBasePath =
|
let make (client : System.Net.Http.HttpClient) : IApiWithBasePath =
|
||||||
@@ -1080,8 +1156,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module ApiWithBasePathAndAddress =
|
module ApiWithBasePathAndAddress =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IApiWithBasePathAndAddress =
|
let make (client : System.Net.Http.HttpClient) : IApiWithBasePathAndAddress =
|
||||||
@@ -1126,8 +1201,7 @@ open System.Net.Http
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module ApiWithHeaders =
|
module ApiWithHeaders =
|
||||||
/// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties.
|
/// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties.
|
||||||
let make
|
let make
|
||||||
@@ -1140,6 +1214,68 @@ 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
|
||||||
|
@@ -149,6 +149,37 @@ module JsonRecordTypeWithBothJsonSerializeExtension =
|
|||||||
)
|
)
|
||||||
|
|
||||||
node :> _
|
node :> _
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Collections.Generic
|
||||||
|
open System.Text.Json.Serialization
|
||||||
|
|
||||||
|
/// Module containing JSON serializing extension members for the FirstDu type
|
||||||
|
[<AutoOpen>]
|
||||||
|
module FirstDuJsonSerializeExtension =
|
||||||
|
/// Extension methods for JSON parsing
|
||||||
|
type FirstDu with
|
||||||
|
|
||||||
|
/// Serialize to a JSON node
|
||||||
|
static member toJsonNode (input : FirstDu) : System.Text.Json.Nodes.JsonNode =
|
||||||
|
let node = System.Text.Json.Nodes.JsonObject ()
|
||||||
|
|
||||||
|
match input with
|
||||||
|
| FirstDu.EmptyCase -> node.Add ("type", System.Text.Json.Nodes.JsonValue.Create "emptyCase")
|
||||||
|
| FirstDu.Case1 arg0 ->
|
||||||
|
node.Add ("type", System.Text.Json.Nodes.JsonValue.Create "case1")
|
||||||
|
let dataNode = System.Text.Json.Nodes.JsonObject ()
|
||||||
|
dataNode.Add ("data", System.Text.Json.Nodes.JsonValue.Create<string> arg0)
|
||||||
|
node.Add ("data", dataNode)
|
||||||
|
| FirstDu.Case2 (arg0, arg1) ->
|
||||||
|
node.Add ("type", System.Text.Json.Nodes.JsonValue.Create "case2")
|
||||||
|
let dataNode = System.Text.Json.Nodes.JsonObject ()
|
||||||
|
dataNode.Add ("record", JsonRecordTypeWithBoth.toJsonNode arg0)
|
||||||
|
dataNode.Add ("i", System.Text.Json.Nodes.JsonValue.Create<int> arg1)
|
||||||
|
node.Add ("data", dataNode)
|
||||||
|
|
||||||
|
node :> _
|
||||||
|
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
@@ -160,7 +191,7 @@ module InnerTypeWithBothJsonParseExtension =
|
|||||||
|
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerTypeWithBoth =
|
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerTypeWithBoth =
|
||||||
let ConcreteDict =
|
let arg_4 =
|
||||||
(match node.["concreteDict"] with
|
(match node.["concreteDict"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -178,7 +209,7 @@ module InnerTypeWithBothJsonParseExtension =
|
|||||||
|> Seq.map System.Collections.Generic.KeyValuePair
|
|> Seq.map System.Collections.Generic.KeyValuePair
|
||||||
|> System.Collections.Generic.Dictionary
|
|> System.Collections.Generic.Dictionary
|
||||||
|
|
||||||
let Dict =
|
let arg_3 =
|
||||||
(match node.["dict"] with
|
(match node.["dict"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -195,7 +226,7 @@ module InnerTypeWithBothJsonParseExtension =
|
|||||||
)
|
)
|
||||||
|> dict
|
|> dict
|
||||||
|
|
||||||
let ReadOnlyDict =
|
let arg_2 =
|
||||||
(match node.["readOnlyDict"] with
|
(match node.["readOnlyDict"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -210,14 +241,14 @@ module InnerTypeWithBothJsonParseExtension =
|
|||||||
|
|
||||||
let value =
|
let value =
|
||||||
(kvp.Value).AsArray ()
|
(kvp.Value).AsArray ()
|
||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<char> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<System.Char> ())
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
key, value
|
key, value
|
||||||
)
|
)
|
||||||
|> readOnlyDict
|
|> readOnlyDict
|
||||||
|
|
||||||
let Map =
|
let arg_1 =
|
||||||
(match node.["map"] with
|
(match node.["map"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -234,7 +265,7 @@ module InnerTypeWithBothJsonParseExtension =
|
|||||||
)
|
)
|
||||||
|> Map.ofSeq
|
|> Map.ofSeq
|
||||||
|
|
||||||
let Thing =
|
let arg_0 =
|
||||||
(match node.[("it's-a-me")] with
|
(match node.[("it's-a-me")] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -248,11 +279,11 @@ module InnerTypeWithBothJsonParseExtension =
|
|||||||
|> System.Guid.Parse
|
|> System.Guid.Parse
|
||||||
|
|
||||||
{
|
{
|
||||||
Thing = Thing
|
Thing = arg_0
|
||||||
Map = Map
|
Map = arg_1
|
||||||
ReadOnlyDict = ReadOnlyDict
|
ReadOnlyDict = arg_2
|
||||||
Dict = Dict
|
Dict = arg_3
|
||||||
ConcreteDict = ConcreteDict
|
ConcreteDict = arg_4
|
||||||
}
|
}
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
@@ -264,7 +295,7 @@ module JsonRecordTypeWithBothJsonParseExtension =
|
|||||||
|
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordTypeWithBoth =
|
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordTypeWithBoth =
|
||||||
let F =
|
let arg_5 =
|
||||||
(match node.["f"] with
|
(match node.["f"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -277,7 +308,7 @@ module JsonRecordTypeWithBothJsonParseExtension =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
||||||
|> Array.ofSeq
|
|> Array.ofSeq
|
||||||
|
|
||||||
let E =
|
let arg_4 =
|
||||||
(match node.["e"] with
|
(match node.["e"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -290,7 +321,7 @@ module JsonRecordTypeWithBothJsonParseExtension =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
||||||
|> Array.ofSeq
|
|> Array.ofSeq
|
||||||
|
|
||||||
let D =
|
let arg_3 =
|
||||||
InnerTypeWithBoth.jsonParse (
|
InnerTypeWithBoth.jsonParse (
|
||||||
match node.["d"] with
|
match node.["d"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -302,7 +333,7 @@ module JsonRecordTypeWithBothJsonParseExtension =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let C =
|
let arg_2 =
|
||||||
(match node.["c"] with
|
(match node.["c"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -315,7 +346,7 @@ module JsonRecordTypeWithBothJsonParseExtension =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<int> ())
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let B =
|
let arg_1 =
|
||||||
(match node.["b"] with
|
(match node.["b"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -327,7 +358,7 @@ module JsonRecordTypeWithBothJsonParseExtension =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let A =
|
let arg_0 =
|
||||||
(match node.["a"] with
|
(match node.["a"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -340,10 +371,90 @@ module JsonRecordTypeWithBothJsonParseExtension =
|
|||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
A = A
|
A = arg_0
|
||||||
B = B
|
B = arg_1
|
||||||
C = C
|
C = arg_2
|
||||||
D = D
|
D = arg_3
|
||||||
E = E
|
E = arg_4
|
||||||
F = F
|
F = arg_5
|
||||||
}
|
}
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
/// Module containing JSON parsing extension members for the FirstDu type
|
||||||
|
[<AutoOpen>]
|
||||||
|
module FirstDuJsonParseExtension =
|
||||||
|
/// Extension methods for JSON parsing
|
||||||
|
type FirstDu with
|
||||||
|
|
||||||
|
/// Parse from a JSON node.
|
||||||
|
static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : FirstDu =
|
||||||
|
let ty =
|
||||||
|
(match node.["type"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("type")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
|> (fun v -> v.GetValue<string> ())
|
||||||
|
|
||||||
|
match ty with
|
||||||
|
| "emptyCase" -> FirstDu.EmptyCase
|
||||||
|
| "case1" ->
|
||||||
|
let node =
|
||||||
|
(match node.["data"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("data")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
|
||||||
|
FirstDu.Case1 (
|
||||||
|
(match node.["data"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("data")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<string> ()
|
||||||
|
)
|
||||||
|
| "case2" ->
|
||||||
|
let node =
|
||||||
|
(match node.["data"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("data")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
|
||||||
|
FirstDu.Case2 (
|
||||||
|
JsonRecordTypeWithBoth.jsonParse (
|
||||||
|
match node.["record"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("record")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v
|
||||||
|
),
|
||||||
|
(match node.["i"] with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.Collections.Generic.KeyNotFoundException (
|
||||||
|
sprintf "Required key '%s' not found on JSON object" ("i")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v)
|
||||||
|
.AsValue()
|
||||||
|
.GetValue<int> ()
|
||||||
|
)
|
||||||
|
| v -> failwith ("Unrecognised 'type' field value: " + v)
|
||||||
|
@@ -8,12 +8,11 @@
|
|||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JwtVaultAuthResponse type
|
/// Module containing JSON parsing methods for the JwtVaultAuthResponse type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JwtVaultAuthResponse =
|
module JwtVaultAuthResponse =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultAuthResponse =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultAuthResponse =
|
||||||
let NumUses =
|
let arg_10 =
|
||||||
(match node.["num_uses"] with
|
(match node.["num_uses"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -25,7 +24,7 @@ module JwtVaultAuthResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Orphan =
|
let arg_9 =
|
||||||
(match node.["orphan"] with
|
(match node.["orphan"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -37,7 +36,7 @@ module JwtVaultAuthResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
let EntityId =
|
let arg_8 =
|
||||||
(match node.["entity_id"] with
|
(match node.["entity_id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -49,7 +48,7 @@ module JwtVaultAuthResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let TokenType =
|
let arg_7 =
|
||||||
(match node.["token_type"] with
|
(match node.["token_type"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -61,7 +60,7 @@ module JwtVaultAuthResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let Renewable =
|
let arg_6 =
|
||||||
(match node.["renewable"] with
|
(match node.["renewable"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -73,7 +72,7 @@ module JwtVaultAuthResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
let LeaseDuration =
|
let arg_5 =
|
||||||
(match node.["lease_duration"] with
|
(match node.["lease_duration"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -85,7 +84,7 @@ module JwtVaultAuthResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let IdentityPolicies =
|
let arg_4 =
|
||||||
(match node.["identity_policies"] with
|
(match node.["identity_policies"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -98,7 +97,7 @@ module JwtVaultAuthResponse =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let TokenPolicies =
|
let arg_3 =
|
||||||
(match node.["token_policies"] with
|
(match node.["token_policies"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -111,7 +110,7 @@ module JwtVaultAuthResponse =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let Policies =
|
let arg_2 =
|
||||||
(match node.["policies"] with
|
(match node.["policies"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -124,7 +123,7 @@ module JwtVaultAuthResponse =
|
|||||||
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
|> Seq.map (fun elt -> elt.AsValue().GetValue<string> ())
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let Accessor =
|
let arg_1 =
|
||||||
(match node.["accessor"] with
|
(match node.["accessor"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -136,7 +135,7 @@ module JwtVaultAuthResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let ClientToken =
|
let arg_0 =
|
||||||
(match node.["client_token"] with
|
(match node.["client_token"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -149,27 +148,26 @@ module JwtVaultAuthResponse =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
ClientToken = ClientToken
|
ClientToken = arg_0
|
||||||
Accessor = Accessor
|
Accessor = arg_1
|
||||||
Policies = Policies
|
Policies = arg_2
|
||||||
TokenPolicies = TokenPolicies
|
TokenPolicies = arg_3
|
||||||
IdentityPolicies = IdentityPolicies
|
IdentityPolicies = arg_4
|
||||||
LeaseDuration = LeaseDuration
|
LeaseDuration = arg_5
|
||||||
Renewable = Renewable
|
Renewable = arg_6
|
||||||
TokenType = TokenType
|
TokenType = arg_7
|
||||||
EntityId = EntityId
|
EntityId = arg_8
|
||||||
Orphan = Orphan
|
Orphan = arg_9
|
||||||
NumUses = NumUses
|
NumUses = arg_10
|
||||||
}
|
}
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JwtVaultResponse type
|
/// Module containing JSON parsing methods for the JwtVaultResponse type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JwtVaultResponse =
|
module JwtVaultResponse =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultResponse =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultResponse =
|
||||||
let Auth =
|
let arg_4 =
|
||||||
JwtVaultAuthResponse.jsonParse (
|
JwtVaultAuthResponse.jsonParse (
|
||||||
match node.["auth"] with
|
match node.["auth"] with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -181,7 +179,7 @@ module JwtVaultResponse =
|
|||||||
| v -> v
|
| v -> v
|
||||||
)
|
)
|
||||||
|
|
||||||
let LeaseDuration =
|
let arg_3 =
|
||||||
(match node.["lease_duration"] with
|
(match node.["lease_duration"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -193,7 +191,7 @@ module JwtVaultResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Renewable =
|
let arg_2 =
|
||||||
(match node.["renewable"] with
|
(match node.["renewable"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -205,7 +203,7 @@ module JwtVaultResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
let LeaseId =
|
let arg_1 =
|
||||||
(match node.["lease_id"] with
|
(match node.["lease_id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -217,7 +215,7 @@ module JwtVaultResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let RequestId =
|
let arg_0 =
|
||||||
(match node.["request_id"] with
|
(match node.["request_id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -230,21 +228,20 @@ module JwtVaultResponse =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
RequestId = RequestId
|
RequestId = arg_0
|
||||||
LeaseId = LeaseId
|
LeaseId = arg_1
|
||||||
Renewable = Renewable
|
Renewable = arg_2
|
||||||
LeaseDuration = LeaseDuration
|
LeaseDuration = arg_3
|
||||||
Auth = Auth
|
Auth = arg_4
|
||||||
}
|
}
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
|
|
||||||
/// Module containing JSON parsing methods for the JwtSecretResponse type
|
/// Module containing JSON parsing methods for the JwtSecretResponse type
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
||||||
module JwtSecretResponse =
|
module JwtSecretResponse =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtSecretResponse =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtSecretResponse =
|
||||||
let Data8 =
|
let arg_11 =
|
||||||
(match node.["data8"] with
|
(match node.["data8"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -262,7 +259,7 @@ module JwtSecretResponse =
|
|||||||
|> Seq.map System.Collections.Generic.KeyValuePair
|
|> Seq.map System.Collections.Generic.KeyValuePair
|
||||||
|> System.Collections.Generic.Dictionary
|
|> System.Collections.Generic.Dictionary
|
||||||
|
|
||||||
let Data7 =
|
let arg_10 =
|
||||||
(match node.["data7"] with
|
(match node.["data7"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -279,7 +276,7 @@ module JwtSecretResponse =
|
|||||||
)
|
)
|
||||||
|> Map.ofSeq
|
|> Map.ofSeq
|
||||||
|
|
||||||
let Data6 =
|
let arg_9 =
|
||||||
(match node.["data6"] with
|
(match node.["data6"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -296,7 +293,7 @@ module JwtSecretResponse =
|
|||||||
)
|
)
|
||||||
|> dict
|
|> dict
|
||||||
|
|
||||||
let Data5 =
|
let arg_8 =
|
||||||
(match node.["data5"] with
|
(match node.["data5"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -313,7 +310,7 @@ module JwtSecretResponse =
|
|||||||
)
|
)
|
||||||
|> readOnlyDict
|
|> readOnlyDict
|
||||||
|
|
||||||
let Data4 =
|
let arg_7 =
|
||||||
(match node.["data4"] with
|
(match node.["data4"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -330,7 +327,7 @@ module JwtSecretResponse =
|
|||||||
)
|
)
|
||||||
|> Map.ofSeq
|
|> Map.ofSeq
|
||||||
|
|
||||||
let Data3 =
|
let arg_6 =
|
||||||
(match node.["data3"] with
|
(match node.["data3"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -348,7 +345,7 @@ module JwtSecretResponse =
|
|||||||
|> Seq.map System.Collections.Generic.KeyValuePair
|
|> Seq.map System.Collections.Generic.KeyValuePair
|
||||||
|> System.Collections.Generic.Dictionary
|
|> System.Collections.Generic.Dictionary
|
||||||
|
|
||||||
let Data2 =
|
let arg_5 =
|
||||||
(match node.["data2"] with
|
(match node.["data2"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -365,7 +362,7 @@ module JwtSecretResponse =
|
|||||||
)
|
)
|
||||||
|> dict
|
|> dict
|
||||||
|
|
||||||
let Data =
|
let arg_4 =
|
||||||
(match node.["data"] with
|
(match node.["data"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -382,7 +379,7 @@ module JwtSecretResponse =
|
|||||||
)
|
)
|
||||||
|> readOnlyDict
|
|> readOnlyDict
|
||||||
|
|
||||||
let LeaseDuration =
|
let arg_3 =
|
||||||
(match node.["lease_duration"] with
|
(match node.["lease_duration"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -394,7 +391,7 @@ module JwtSecretResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<int> ()
|
.GetValue<int> ()
|
||||||
|
|
||||||
let Renewable =
|
let arg_2 =
|
||||||
(match node.["renewable"] with
|
(match node.["renewable"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -406,7 +403,7 @@ module JwtSecretResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<bool> ()
|
.GetValue<bool> ()
|
||||||
|
|
||||||
let LeaseId =
|
let arg_1 =
|
||||||
(match node.["lease_id"] with
|
(match node.["lease_id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -418,7 +415,7 @@ module JwtSecretResponse =
|
|||||||
.AsValue()
|
.AsValue()
|
||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
let RequestId =
|
let arg_0 =
|
||||||
(match node.["request_id"] with
|
(match node.["request_id"] with
|
||||||
| null ->
|
| null ->
|
||||||
raise (
|
raise (
|
||||||
@@ -431,18 +428,18 @@ module JwtSecretResponse =
|
|||||||
.GetValue<string> ()
|
.GetValue<string> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
RequestId = RequestId
|
RequestId = arg_0
|
||||||
LeaseId = LeaseId
|
LeaseId = arg_1
|
||||||
Renewable = Renewable
|
Renewable = arg_2
|
||||||
LeaseDuration = LeaseDuration
|
LeaseDuration = arg_3
|
||||||
Data = Data
|
Data = arg_4
|
||||||
Data2 = Data2
|
Data2 = arg_5
|
||||||
Data3 = Data3
|
Data3 = arg_6
|
||||||
Data4 = Data4
|
Data4 = arg_7
|
||||||
Data5 = Data5
|
Data5 = arg_8
|
||||||
Data6 = Data6
|
Data6 = arg_9
|
||||||
Data7 = Data7
|
Data7 = arg_10
|
||||||
Data8 = Data8
|
Data8 = arg_11
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ConsumePlugin
|
namespace ConsumePlugin
|
||||||
@@ -455,8 +452,7 @@ open System.Threading.Tasks
|
|||||||
open RestEase
|
open RestEase
|
||||||
|
|
||||||
/// Module for constructing a REST client.
|
/// Module for constructing a REST client.
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module VaultClient =
|
module VaultClient =
|
||||||
/// Create a REST client.
|
/// Create a REST client.
|
||||||
let make (client : System.Net.Http.HttpClient) : IVaultClient =
|
let make (client : System.Net.Http.HttpClient) : IVaultClient =
|
||||||
@@ -543,3 +539,200 @@ module VaultClient =
|
|||||||
}
|
}
|
||||||
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
}
|
}
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Collections.Generic
|
||||||
|
open System.Text.Json.Serialization
|
||||||
|
open System.Threading
|
||||||
|
open System.Threading.Tasks
|
||||||
|
open RestEase
|
||||||
|
|
||||||
|
/// Module for constructing a REST client.
|
||||||
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
|
module VaultClientNonExtensionMethod =
|
||||||
|
/// Create a REST client.
|
||||||
|
let make (client : System.Net.Http.HttpClient) : IVaultClientNonExtensionMethod =
|
||||||
|
{ new IVaultClientNonExtensionMethod with
|
||||||
|
member _.GetSecret
|
||||||
|
(jwt : JwtVaultResponse, path : string, mountPoint : 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 (
|
||||||
|
"v1/{mountPoint}/{path}"
|
||||||
|
.Replace("{path}", path.ToString () |> System.Web.HttpUtility.UrlEncode)
|
||||||
|
.Replace (
|
||||||
|
"{mountPoint}",
|
||||||
|
mountPoint.ToString () |> 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 JwtSecretResponse.jsonParse jsonNode
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
|
||||||
|
member _.GetJwt (role : string, jwt : 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 ("v1/auth/jwt/login", 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 JwtVaultResponse.jsonParse jsonNode
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
}
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Collections.Generic
|
||||||
|
open System.Text.Json.Serialization
|
||||||
|
open System.Threading
|
||||||
|
open System.Threading.Tasks
|
||||||
|
open RestEase
|
||||||
|
|
||||||
|
/// Extension methods for constructing a REST client.
|
||||||
|
[<AutoOpen>]
|
||||||
|
module VaultClientExtensionMethodHttpClientExtension =
|
||||||
|
/// Extension methods for HTTP clients
|
||||||
|
type VaultClientExtensionMethod with
|
||||||
|
|
||||||
|
/// Create a REST client.
|
||||||
|
static member make (client : System.Net.Http.HttpClient) : IVaultClientExtensionMethod =
|
||||||
|
{ new IVaultClientExtensionMethod with
|
||||||
|
member _.GetSecret
|
||||||
|
(jwt : JwtVaultResponse, path : string, mountPoint : 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 (
|
||||||
|
"v1/{mountPoint}/{path}"
|
||||||
|
.Replace("{path}", path.ToString () |> System.Web.HttpUtility.UrlEncode)
|
||||||
|
.Replace (
|
||||||
|
"{mountPoint}",
|
||||||
|
mountPoint.ToString () |> 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 JwtSecretResponse.jsonParse jsonNode
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
|
||||||
|
member _.GetJwt (role : string, jwt : 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 ("v1/auth/jwt/login", 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 JwtVaultResponse.jsonParse jsonNode
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
}
|
||||||
|
@@ -29,13 +29,52 @@ type JsonRecordType =
|
|||||||
F : int[]
|
F : int[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonParse>]
|
||||||
|
type internal InternalTypeNotExtension =
|
||||||
|
{
|
||||||
|
[<JsonPropertyName(Literals.something)>]
|
||||||
|
InternalThing : string
|
||||||
|
}
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonSerialize>]
|
||||||
|
type internal InternalTypeNotExtensionSerial =
|
||||||
|
{
|
||||||
|
[<JsonPropertyName(Literals.something)>]
|
||||||
|
InternalThing2 : string
|
||||||
|
}
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonParse true>]
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonSerialize true>]
|
||||||
|
type internal InternalTypeExtension =
|
||||||
|
{
|
||||||
|
[<JsonPropertyName(Literals.something)>]
|
||||||
|
ExternalThing : string
|
||||||
|
}
|
||||||
|
|
||||||
[<WoofWare.Myriad.Plugins.JsonParse true>]
|
[<WoofWare.Myriad.Plugins.JsonParse true>]
|
||||||
type ToGetExtensionMethod =
|
type ToGetExtensionMethod =
|
||||||
{
|
{
|
||||||
Tinker : string
|
Alpha : string
|
||||||
Tailor : int
|
Bravo : System.Uri
|
||||||
Soldier : System.Uri
|
Charlie : float
|
||||||
Sailor : float
|
Delta : float32
|
||||||
|
Echo : single
|
||||||
|
Foxtrot : double
|
||||||
|
Golf : int64
|
||||||
|
Hotel : uint64
|
||||||
|
India : int
|
||||||
|
Juliette : uint
|
||||||
|
Kilo : int32
|
||||||
|
Lima : uint32
|
||||||
|
Mike : int16
|
||||||
|
November : uint16
|
||||||
|
Oscar : int8
|
||||||
|
Papa : uint8
|
||||||
|
Quebec : byte
|
||||||
|
Tango : sbyte
|
||||||
|
Uniform : decimal
|
||||||
|
Victor : char
|
||||||
|
Whiskey : bigint
|
||||||
}
|
}
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
|
@@ -50,7 +50,7 @@ module MyListCata =
|
|||||||
}) ->
|
}) ->
|
||||||
instructions.Add (Instruction.MyList_Cons (head))
|
instructions.Add (Instruction.MyList_Cons (head))
|
||||||
instructions.Add (Instruction.Process__MyList tail)
|
instructions.Add (Instruction.Process__MyList tail)
|
||||||
| Instruction.MyList_Cons (head) ->
|
| Instruction.MyList_Cons head ->
|
||||||
let tail = myListStack.[myListStack.Count - 1]
|
let tail = myListStack.[myListStack.Count - 1]
|
||||||
myListStack.RemoveAt (myListStack.Count - 1)
|
myListStack.RemoveAt (myListStack.Count - 1)
|
||||||
cata.MyList.Cons head tail |> myListStack.Add
|
cata.MyList.Cons head tail |> myListStack.Add
|
||||||
@@ -103,7 +103,7 @@ module MyList2Cata =
|
|||||||
| MyList2.Cons (arg0_0, arg1_0) ->
|
| MyList2.Cons (arg0_0, arg1_0) ->
|
||||||
instructions.Add (Instruction.MyList2_Cons (arg0_0))
|
instructions.Add (Instruction.MyList2_Cons (arg0_0))
|
||||||
instructions.Add (Instruction.Process__MyList2 arg1_0)
|
instructions.Add (Instruction.Process__MyList2 arg1_0)
|
||||||
| Instruction.MyList2_Cons (arg0_0) ->
|
| Instruction.MyList2_Cons arg0_0 ->
|
||||||
let arg1_0 = myList2Stack.[myList2Stack.Count - 1]
|
let arg1_0 = myList2Stack.[myList2Stack.Count - 1]
|
||||||
myList2Stack.RemoveAt (myList2Stack.Count - 1)
|
myList2Stack.RemoveAt (myList2Stack.Count - 1)
|
||||||
cata.MyList2.Cons arg0_0 arg1_0 |> myList2Stack.Add
|
cata.MyList2.Cons arg0_0 arg1_0 |> myList2Stack.Add
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
namespace SomeNamespace
|
namespace SomeNamespace
|
||||||
|
|
||||||
|
open System
|
||||||
open WoofWare.Myriad.Plugins
|
open WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
[<GenerateMock>]
|
[<GenerateMock>]
|
||||||
@@ -41,3 +42,9 @@ 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
|
||||||
|
@@ -17,6 +17,9 @@ type IPureGymApi =
|
|||||||
[<Get "v1/gyms/{gym_id}/attendance">]
|
[<Get "v1/gyms/{gym_id}/attendance">]
|
||||||
abstract GetGymAttendance : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<GymAttendance>
|
abstract GetGymAttendance : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<GymAttendance>
|
||||||
|
|
||||||
|
[<Get "v1/gyms/{gym_id}/attendance">]
|
||||||
|
abstract GetGymAttendance' : [<Path("gym_id")>] gymId : int * ?ct : CancellationToken -> Task<GymAttendance>
|
||||||
|
|
||||||
[<RestEase.GetAttribute "v1/member">]
|
[<RestEase.GetAttribute "v1/member">]
|
||||||
abstract GetMember : ?ct : CancellationToken -> Member Task
|
abstract GetMember : ?ct : CancellationToken -> Member Task
|
||||||
|
|
||||||
@@ -38,6 +41,10 @@ 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>
|
||||||
@@ -120,7 +127,8 @@ type internal IApiWithoutBaseAddress =
|
|||||||
[<WoofWare.Myriad.Plugins.HttpClient>]
|
[<WoofWare.Myriad.Plugins.HttpClient>]
|
||||||
[<BasePath "foo">]
|
[<BasePath "foo">]
|
||||||
type IApiWithBasePath =
|
type IApiWithBasePath =
|
||||||
[<Get "endpoint/{param}">]
|
// Example where we use the bundled attributes rather than RestEase's
|
||||||
|
[<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>]
|
||||||
@@ -141,3 +149,16 @@ 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>
|
||||||
|
@@ -27,3 +27,10 @@ type JsonRecordTypeWithBoth =
|
|||||||
E : string array
|
E : string array
|
||||||
F : int[]
|
F : int[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonSerialize true>]
|
||||||
|
[<WoofWare.Myriad.Plugins.JsonParse true>]
|
||||||
|
type FirstDu =
|
||||||
|
| EmptyCase
|
||||||
|
| Case1 of data : string
|
||||||
|
| Case2 of record : JsonRecordTypeWithBoth * i : int
|
||||||
|
@@ -76,3 +76,33 @@ type IVaultClient =
|
|||||||
|
|
||||||
[<Get "v1/auth/jwt/login">]
|
[<Get "v1/auth/jwt/login">]
|
||||||
abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse>
|
abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse>
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.HttpClient false>]
|
||||||
|
type IVaultClientNonExtensionMethod =
|
||||||
|
[<Get "v1/{mountPoint}/{path}">]
|
||||||
|
abstract GetSecret :
|
||||||
|
jwt : JwtVaultResponse *
|
||||||
|
[<Path "path">] path : string *
|
||||||
|
[<Path "mountPoint">] mountPoint : string *
|
||||||
|
?ct : CancellationToken ->
|
||||||
|
Task<JwtSecretResponse>
|
||||||
|
|
||||||
|
[<Get "v1/auth/jwt/login">]
|
||||||
|
abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse>
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.HttpClient(true)>]
|
||||||
|
type IVaultClientExtensionMethod =
|
||||||
|
[<Get "v1/{mountPoint}/{path}">]
|
||||||
|
abstract GetSecret :
|
||||||
|
jwt : JwtVaultResponse *
|
||||||
|
[<Path "path">] path : string *
|
||||||
|
[<Path "mountPoint">] mountPoint : string *
|
||||||
|
?ct : CancellationToken ->
|
||||||
|
Task<JwtSecretResponse>
|
||||||
|
|
||||||
|
[<Get "v1/auth/jwt/login">]
|
||||||
|
abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse>
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
type VaultClientExtensionMethod =
|
||||||
|
static member thisClashes = 99
|
||||||
|
@@ -10,19 +10,10 @@
|
|||||||
<WarnOn>FS3388,FS3559</WarnOn>
|
<WarnOn>FS3388,FS3559</WarnOn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.133" PrivateAssets="all"/>
|
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.139" PrivateAssets="all"/>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
|
|
||||||
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com"/>
|
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!--
|
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">
|
||||||
SourceLink doesn't support F# deterministic builds out of the box,
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
so tell SourceLink that our source root is going to be remapped.
|
</PropertyGroup>
|
||||||
-->
|
|
||||||
<Target Name="MapSourceRoot" BeforeTargets="_GenerateSourceLinkFile" Condition="'$(SourceRootMappedPathsFeatureSupported)' != 'true'">
|
|
||||||
<ItemGroup>
|
|
||||||
<SourceRoot Update="@(SourceRoot)">
|
|
||||||
<MappedPath>Z:\CheckoutRoot\WoofWare.Myriad\</MappedPath>
|
|
||||||
</SourceRoot>
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -143,6 +143,9 @@ module InnerTypeWithBoth =
|
|||||||
node
|
node
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Also includes an *opinionated* serializer for discriminated unions.
|
||||||
|
(Any such serializer must be opinionated, because JSON does not natively model DUs.)
|
||||||
|
|
||||||
As in `JsonParse`, you can optionally supply the boolean `true` to the attribute,
|
As in `JsonParse`, you can optionally supply the boolean `true` to the attribute,
|
||||||
which will cause Myriad to stamp out an extension method rather than a module with the same name as the type.
|
which will cause Myriad to stamp out an extension method rather than a module with the same name as the type.
|
||||||
|
|
||||||
|
@@ -60,8 +60,17 @@ type JsonParseAttribute (isExtensionMethod : bool) =
|
|||||||
/// generator should apply during build.
|
/// generator should apply during build.
|
||||||
/// This generator is intended to replicate much of the functionality of RestEase,
|
/// This generator is intended to replicate much of the functionality of RestEase,
|
||||||
/// i.e. to stamp out HTTP REST clients from interfaces defining the API.
|
/// i.e. to stamp out HTTP REST clients from interfaces defining the API.
|
||||||
type HttpClientAttribute () =
|
///
|
||||||
|
/// If you supply isExtensionMethod = true, you will get extension methods.
|
||||||
|
/// These can only be consumed from F#, but the benefit is that they don't use up the module name
|
||||||
|
/// (since by default we create a module called "{TypeName}").
|
||||||
|
type HttpClientAttribute (isExtensionMethod : bool) =
|
||||||
inherit Attribute ()
|
inherit Attribute ()
|
||||||
|
/// The default value of `isExtensionMethod`, the optional argument to the HttpClientAttribute constructor.
|
||||||
|
static member DefaultIsExtensionMethod = false
|
||||||
|
|
||||||
|
/// Shorthand for the "isExtensionMethod = false" constructor; see documentation there for details.
|
||||||
|
new () = HttpClientAttribute HttpClientAttribute.DefaultIsExtensionMethod
|
||||||
|
|
||||||
/// Attribute indicating a DU type to which the "create catamorphism" Myriad
|
/// Attribute indicating a DU type to which the "create catamorphism" Myriad
|
||||||
/// generator should apply during build.
|
/// generator should apply during build.
|
||||||
|
63
WoofWare.Myriad.Plugins.Attributes/RestEase.fs
Normal file
63
WoofWare.Myriad.Plugins.Attributes/RestEase.fs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
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
|
@@ -6,7 +6,10 @@ WoofWare.Myriad.Plugins.GenerateMockAttribute..ctor [constructor]: unit
|
|||||||
WoofWare.Myriad.Plugins.GenerateMockAttribute.DefaultIsInternal [static property]: [read-only] bool
|
WoofWare.Myriad.Plugins.GenerateMockAttribute.DefaultIsInternal [static property]: [read-only] bool
|
||||||
WoofWare.Myriad.Plugins.GenerateMockAttribute.get_DefaultIsInternal [static method]: unit -> bool
|
WoofWare.Myriad.Plugins.GenerateMockAttribute.get_DefaultIsInternal [static method]: unit -> bool
|
||||||
WoofWare.Myriad.Plugins.HttpClientAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.HttpClientAttribute inherit System.Attribute
|
||||||
|
WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: bool
|
||||||
WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: unit
|
WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: unit
|
||||||
|
WoofWare.Myriad.Plugins.HttpClientAttribute.DefaultIsExtensionMethod [static property]: [read-only] bool
|
||||||
|
WoofWare.Myriad.Plugins.HttpClientAttribute.get_DefaultIsExtensionMethod [static method]: unit -> bool
|
||||||
WoofWare.Myriad.Plugins.JsonParseAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.JsonParseAttribute inherit System.Attribute
|
||||||
WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: bool
|
WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: bool
|
||||||
WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: unit
|
WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: unit
|
||||||
@@ -18,4 +21,33 @@ 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
|
@@ -11,11 +11,9 @@ 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`` () =
|
||||||
|
@@ -12,8 +12,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ApiSurface" Version="4.0.33" />
|
<PackageReference Include="ApiSurface" Version="4.0.41" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
||||||
<PackageReference Include="NUnit" Version="4.1.0"/>
|
<PackageReference Include="NUnit" Version="4.1.0"/>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
<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">
|
||||||
|
@@ -1,7 +1,15 @@
|
|||||||
{
|
{
|
||||||
"version": "2.2",
|
"version": "3.1",
|
||||||
"publicReleaseRefSpec": [
|
"publicReleaseRefSpec": [
|
||||||
"^refs/heads/main$"
|
"^refs/heads/main$"
|
||||||
],
|
],
|
||||||
"pathFilters": null
|
"pathFilters": [
|
||||||
|
":/README.md",
|
||||||
|
":/LICENSE",
|
||||||
|
":/WoofWare.Myriad.Plugins/logo.png",
|
||||||
|
":/Directory.Build.props",
|
||||||
|
":/global.json",
|
||||||
|
"./",
|
||||||
|
"^./Test"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@@ -89,6 +89,7 @@ module TestPureGymRestApi =
|
|||||||
let api = PureGymApi.make client
|
let api = PureGymApi.make client
|
||||||
|
|
||||||
api.GetGymAttendance(requestedGym).Result |> shouldEqual expected
|
api.GetGymAttendance(requestedGym).Result |> shouldEqual expected
|
||||||
|
api.GetGymAttendance'(requestedGym).Result |> shouldEqual expected
|
||||||
|
|
||||||
let memberCases =
|
let memberCases =
|
||||||
PureGymDtos.memberCases |> List.allPairs baseUris |> List.map TestCaseData
|
PureGymDtos.memberCases |> List.allPairs baseUris |> List.map TestCaseData
|
||||||
@@ -234,6 +235,33 @@ 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 =
|
||||||
|
@@ -87,8 +87,10 @@ module TestVaultClient =
|
|||||||
}
|
}
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
[<Test>]
|
[<TestCase 1>]
|
||||||
let ``URI example`` () =
|
[<TestCase 2>]
|
||||||
|
[<TestCase 3>]
|
||||||
|
let ``URI example`` (vaultClientId : int) =
|
||||||
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
async {
|
async {
|
||||||
message.Method |> shouldEqual HttpMethod.Get
|
message.Method |> shouldEqual HttpMethod.Get
|
||||||
@@ -112,10 +114,25 @@ module TestVaultClient =
|
|||||||
}
|
}
|
||||||
|
|
||||||
use client = HttpClientMock.make (Uri "https://my-vault.com") proc
|
use client = HttpClientMock.make (Uri "https://my-vault.com") proc
|
||||||
let api = VaultClient.make client
|
|
||||||
|
|
||||||
let vaultResponse = api.GetJwt("role", "jwt").Result
|
let value =
|
||||||
let value = api.GetSecret(vaultResponse, "path", "mount").Result
|
match vaultClientId with
|
||||||
|
| 1 ->
|
||||||
|
let api = VaultClient.make client
|
||||||
|
let vaultResponse = api.GetJwt("role", "jwt").Result
|
||||||
|
let value = api.GetSecret(vaultResponse, "path", "mount").Result
|
||||||
|
value
|
||||||
|
| 2 ->
|
||||||
|
let api = VaultClientNonExtensionMethod.make client
|
||||||
|
let vaultResponse = api.GetJwt("role", "jwt").Result
|
||||||
|
let value = api.GetSecret(vaultResponse, "path", "mount").Result
|
||||||
|
value
|
||||||
|
| 3 ->
|
||||||
|
let api = VaultClientExtensionMethod.make client
|
||||||
|
let vaultResponse = api.GetJwt("role", "jwt").Result
|
||||||
|
let value = api.GetSecret(vaultResponse, "path", "mount").Result
|
||||||
|
value
|
||||||
|
| _ -> failwith $"Unrecognised ID: %i{vaultClientId}"
|
||||||
|
|
||||||
value.Data
|
value.Data
|
||||||
|> Seq.toList
|
|> Seq.toList
|
||||||
@@ -168,3 +185,5 @@ module TestVaultClient =
|
|||||||
"key8_1", "https://example.com/data8/1"
|
"key8_1", "https://example.com/data8/1"
|
||||||
"key8_2", "https://example.com/data8/2"
|
"key8_2", "https://example.com/data8/2"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
let _canSeePastExtensionMethod = VaultClientExtensionMethod.thisClashes
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
namespace WoofWare.Myriad.Plugins.Test
|
namespace WoofWare.Myriad.Plugins.Test
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open System.Numerics
|
||||||
open System.Text.Json.Nodes
|
open System.Text.Json.Nodes
|
||||||
open ConsumePlugin
|
open ConsumePlugin
|
||||||
open NUnit.Framework
|
open NUnit.Framework
|
||||||
@@ -12,15 +13,62 @@ module TestExtensionMethod =
|
|||||||
[<Test>]
|
[<Test>]
|
||||||
let ``Parse via extension method`` () =
|
let ``Parse via extension method`` () =
|
||||||
let json =
|
let json =
|
||||||
"""{"tinker": "job", "tailor": 3, "soldier": "https://example.com", "sailor": 3.1}"""
|
"""{
|
||||||
|
"alpha": "hello!",
|
||||||
|
"bravo": "https://example.com",
|
||||||
|
"charlie": 0.3341,
|
||||||
|
"delta": 110033.4,
|
||||||
|
"echo": -0.000993,
|
||||||
|
"foxtrot": -999999999999,
|
||||||
|
"golf": -123456789101112,
|
||||||
|
"hotel": 18446744073709551615,
|
||||||
|
"india": 99884,
|
||||||
|
"juliette": 12223334,
|
||||||
|
"kilo": -2147483642,
|
||||||
|
"lima": 4294967293,
|
||||||
|
"mike": -32767,
|
||||||
|
"november": 65533,
|
||||||
|
"oscar": -125,
|
||||||
|
"papa": 253,
|
||||||
|
"quebec": 254,
|
||||||
|
"tango": -3,
|
||||||
|
"uniform": 1004443.300988393349583009,
|
||||||
|
"victor": "x",
|
||||||
|
"whiskey": 123456123456123456123456123456123456123456
|
||||||
|
}"""
|
||||||
|> JsonNode.Parse
|
|> JsonNode.Parse
|
||||||
|
|
||||||
let expected =
|
let expected =
|
||||||
{
|
{
|
||||||
Tinker = "job"
|
Alpha = "hello!"
|
||||||
Tailor = 3
|
Bravo = Uri "https://example.com"
|
||||||
Soldier = Uri "https://example.com"
|
Charlie = 0.3341
|
||||||
Sailor = 3.1
|
Delta = 110033.4f
|
||||||
|
Echo = -0.000993f
|
||||||
|
Foxtrot = -999999999999.0
|
||||||
|
Golf = -123456789101112L
|
||||||
|
Hotel = 18446744073709551615UL
|
||||||
|
India = 99884
|
||||||
|
Juliette = 12223334u
|
||||||
|
Kilo = -2147483642
|
||||||
|
Lima = 4294967293u
|
||||||
|
Mike = -32767s
|
||||||
|
November = 65533us
|
||||||
|
Oscar = -125y
|
||||||
|
Papa = 253uy
|
||||||
|
Quebec = 254uy
|
||||||
|
Tango = -3y
|
||||||
|
Uniform = 1004443.300988393349583009m
|
||||||
|
Victor = 'x'
|
||||||
|
Whiskey =
|
||||||
|
let mutable i = BigInteger 0
|
||||||
|
|
||||||
|
for _ = 0 to 6 do
|
||||||
|
i <- i * BigInteger 1000000 + BigInteger 123456
|
||||||
|
|
||||||
|
i
|
||||||
}
|
}
|
||||||
|
|
||||||
ToGetExtensionMethod.jsonParse json |> shouldEqual expected
|
let actual = ToGetExtensionMethod.jsonParse json
|
||||||
|
|
||||||
|
actual |> shouldEqual expected
|
||||||
|
@@ -7,6 +7,8 @@ open FsUnitTyped
|
|||||||
|
|
||||||
[<TestFixture>]
|
[<TestFixture>]
|
||||||
module TestJsonParse =
|
module TestJsonParse =
|
||||||
|
let _canSeePastExtensionMethod = ToGetExtensionMethod.thisModuleWouldClash
|
||||||
|
|
||||||
[<Test>]
|
[<Test>]
|
||||||
let ``Single example`` () =
|
let ``Single example`` () =
|
||||||
let s =
|
let s =
|
||||||
|
@@ -2,10 +2,9 @@ namespace WoofWare.Myriad.Plugins.Test
|
|||||||
|
|
||||||
open System
|
open System
|
||||||
open System.Collections.Generic
|
open System.Collections.Generic
|
||||||
open System.IO
|
|
||||||
open System.Text
|
|
||||||
open System.Text.Json
|
|
||||||
open System.Text.Json.Nodes
|
open System.Text.Json.Nodes
|
||||||
|
open FsCheck.Random
|
||||||
|
open Microsoft.FSharp.Reflection
|
||||||
open NUnit.Framework
|
open NUnit.Framework
|
||||||
open FsCheck
|
open FsCheck
|
||||||
open FsUnitTyped
|
open FsUnitTyped
|
||||||
@@ -124,3 +123,83 @@ module TestJsonSerde =
|
|||||||
|> shouldEqual (
|
|> shouldEqual (
|
||||||
sprintf """{"it\u0027s-a-me":"%s","map":{},"readOnlyDict":{},"dict":{},"concreteDict":{}}""" guidStr
|
sprintf """{"it\u0027s-a-me":"%s","map":{},"readOnlyDict":{},"dict":{},"concreteDict":{}}""" guidStr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Generators =
|
||||||
|
static member TestCase () =
|
||||||
|
{ new Arbitrary<InnerTypeWithBoth>() with
|
||||||
|
override x.Generator = innerGen 5
|
||||||
|
}
|
||||||
|
|
||||||
|
let sanitiseInner (r : InnerTypeWithBoth) : InnerTypeWithBoth =
|
||||||
|
{
|
||||||
|
Thing = r.Thing
|
||||||
|
Map = r.Map
|
||||||
|
ReadOnlyDict = r.ReadOnlyDict
|
||||||
|
Dict = r.Dict
|
||||||
|
ConcreteDict = r.ConcreteDict
|
||||||
|
}
|
||||||
|
|
||||||
|
let sanitiseRec (r : JsonRecordTypeWithBoth) : JsonRecordTypeWithBoth =
|
||||||
|
{
|
||||||
|
A = r.A
|
||||||
|
B = if isNull r.B then "<null>" else r.B
|
||||||
|
C =
|
||||||
|
if Object.ReferenceEquals (r.C, (null : obj)) then
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
r.C
|
||||||
|
D = sanitiseInner r.D
|
||||||
|
E = if isNull r.E then [||] else r.E
|
||||||
|
F =
|
||||||
|
if Object.ReferenceEquals (r.F, (null : obj)) then
|
||||||
|
[||]
|
||||||
|
else
|
||||||
|
r.F
|
||||||
|
}
|
||||||
|
|
||||||
|
let duGen =
|
||||||
|
gen {
|
||||||
|
let! case = Gen.choose (0, 2)
|
||||||
|
|
||||||
|
match case with
|
||||||
|
| 0 -> return FirstDu.EmptyCase
|
||||||
|
| 1 ->
|
||||||
|
let! s = Arb.generate<NonNull<string>>
|
||||||
|
return FirstDu.Case1 s.Get
|
||||||
|
| 2 ->
|
||||||
|
let! i = Arb.generate<int>
|
||||||
|
let! record = outerGen
|
||||||
|
return FirstDu.Case2 (record, i)
|
||||||
|
| _ -> return failwith $"unexpected: %i{case}"
|
||||||
|
}
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Discriminated union works`` () =
|
||||||
|
let property (du : FirstDu) : unit =
|
||||||
|
du
|
||||||
|
|> FirstDu.toJsonNode
|
||||||
|
|> fun s -> s.ToJsonString ()
|
||||||
|
|> JsonNode.Parse
|
||||||
|
|> FirstDu.jsonParse
|
||||||
|
|> shouldEqual du
|
||||||
|
|
||||||
|
property |> Prop.forAll (Arb.fromGen duGen) |> Check.QuickThrowOnFailure
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``DU generator covers all cases`` () =
|
||||||
|
let rand = Random ()
|
||||||
|
let cases = FSharpType.GetUnionCases typeof<FirstDu>
|
||||||
|
let counts = Array.zeroCreate<int> cases.Length
|
||||||
|
|
||||||
|
let decompose = FSharpValue.PreComputeUnionTagReader typeof<FirstDu>
|
||||||
|
|
||||||
|
let mutable i = 0
|
||||||
|
|
||||||
|
while i < 10_000 && Array.exists (fun i -> i = 0) counts do
|
||||||
|
let du = Gen.eval 10 (StdGen.StdGen (rand.Next (), rand.Next ())) duGen
|
||||||
|
let tag = decompose du
|
||||||
|
counts.[tag] <- counts.[tag] + 1
|
||||||
|
i <- i + 1
|
||||||
|
|
||||||
|
for i in counts do
|
||||||
|
i |> shouldBeGreaterThan 0
|
||||||
|
@@ -12,7 +12,8 @@ module TestSurface =
|
|||||||
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`` () =
|
// https://github.com/nunit/nunit3-vs-adapter/issues/876
|
||||||
|
let CheckVersionAgainstRemote () =
|
||||||
MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins"
|
MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins"
|
||||||
|
|
||||||
[<Test ; Explicit>]
|
[<Test ; Explicit>]
|
||||||
|
@@ -33,10 +33,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ApiSurface" Version="4.0.33"/>
|
<PackageReference Include="ApiSurface" Version="4.0.41"/>
|
||||||
<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.10.0"/>
|
||||||
<PackageReference Include="NUnit" Version="4.1.0"/>
|
<PackageReference Include="NUnit" Version="4.1.0"/>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
open Fantomas.FCS.Xml
|
open Fantomas.FCS.Xml
|
||||||
open Myriad.Core.AstExtensions
|
|
||||||
|
|
||||||
type internal ParameterInfo =
|
type internal ParameterInfo =
|
||||||
{
|
{
|
||||||
@@ -54,6 +52,7 @@ 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
|
||||||
@@ -105,81 +104,17 @@ module internal AstHelper =
|
|||||||
SynExpr.Record (None, None, fields, range0)
|
SynExpr.Record (None, None, fields, range0)
|
||||||
|
|
||||||
let defineRecordType (record : RecordType) : SynTypeDefn =
|
let defineRecordType (record : RecordType) : SynTypeDefn =
|
||||||
let repr =
|
|
||||||
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, Seq.toList record.Fields, range0), range0)
|
|
||||||
|
|
||||||
let name =
|
let name =
|
||||||
SynComponentInfo.Create (
|
SynComponentInfo.create record.Name
|
||||||
[ record.Name ],
|
|> SynComponentInfo.setAccessibility record.Accessibility
|
||||||
?xmldoc = record.XmlDoc,
|
|> match record.XmlDoc with
|
||||||
?parameters = record.Generics,
|
| None -> id
|
||||||
access = record.Accessibility
|
| Some doc -> SynComponentInfo.withDocString doc
|
||||||
)
|
|> SynComponentInfo.setGenerics record.Generics
|
||||||
|
|
||||||
let trivia : SynTypeDefnTrivia =
|
SynTypeDefnRepr.record (Seq.toList record.Fields)
|
||||||
{
|
|> SynTypeDefn.create name
|
||||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
|> SynTypeDefn.withMemberDefns (defaultArg record.Members SynMemberDefns.Empty)
|
||||||
EqualsRange = Some range0
|
|
||||||
WithKeyword = Some range0
|
|
||||||
}
|
|
||||||
|
|
||||||
SynTypeDefn (name, repr, defaultArg record.Members SynMemberDefns.Empty, None, range0, trivia)
|
|
||||||
|
|
||||||
let isOptionIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] when System.String.Equals (i.idText, "option", System.StringComparison.OrdinalIgnoreCase) -> true
|
|
||||||
// TODO: consider Microsoft.FSharp.Option or whatever it is
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isListIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true
|
|
||||||
// TODO: consider FSharpList or whatever it is
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isArrayIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] when
|
|
||||||
System.String.Equals (i.idText, "array", System.StringComparison.OrdinalIgnoreCase)
|
|
||||||
|| System.String.Equals (i.idText, "[]", System.StringComparison.Ordinal)
|
|
||||||
->
|
|
||||||
true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isResponseIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "Response" ]
|
|
||||||
| [ "RestEase" ; "Response" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isMapIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "Map" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isReadOnlyDictionaryIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "IReadOnlyDictionary" ]
|
|
||||||
| [ "Generic" ; "IReadOnlyDictionary" ]
|
|
||||||
| [ "Collections" ; "Generic" ; "IReadOnlyDictionary" ]
|
|
||||||
| [ "System" ; "Collections" ; "Generic" ; "IReadOnlyDictionary" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isDictionaryIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "Dictionary" ]
|
|
||||||
| [ "Generic" ; "Dictionary" ]
|
|
||||||
| [ "Collections" ; "Generic" ; "Dictionary" ]
|
|
||||||
| [ "System" ; "Collections" ; "Generic" ; "Dictionary" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let isIDictionaryIdent (ident : SynLongIdent) : bool =
|
|
||||||
match ident.LongIdent |> List.map _.idText with
|
|
||||||
| [ "IDictionary" ]
|
|
||||||
| [ "Generic" ; "IDictionary" ]
|
|
||||||
| [ "Collections" ; "Generic" ; "IDictionary" ]
|
|
||||||
| [ "System" ; "Collections" ; "Generic" ; "IDictionary" ] -> true
|
|
||||||
| _ -> false
|
|
||||||
|
|
||||||
let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list =
|
let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list =
|
||||||
moduleDecls
|
moduleDecls
|
||||||
@@ -201,12 +136,12 @@ module internal AstHelper =
|
|||||||
| SynType.Paren (inner, _) ->
|
| SynType.Paren (inner, _) ->
|
||||||
let result, _ = convertSigParam inner
|
let result, _ = convertSigParam inner
|
||||||
result, true
|
result, true
|
||||||
| SynType.LongIdent ident ->
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
{
|
{
|
||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.CreateLongIdent ident
|
Type = SynType.createLongIdent ident
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
| SynType.SignatureParameter (attrs, opt, id, usedType, _) ->
|
| SynType.SignatureParameter (attrs, opt, id, usedType, _) ->
|
||||||
@@ -224,7 +159,7 @@ module internal AstHelper =
|
|||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.Var (typar, range0)
|
Type = SynType.var typar
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
| _ -> failwithf "expected SignatureParameter, got: %+A" ty
|
| _ -> failwithf "expected SignatureParameter, got: %+A" ty
|
||||||
@@ -253,10 +188,6 @@ module internal AstHelper =
|
|||||||
}
|
}
|
||||||
| _ -> failwithf "Didn't have alternating type-and-star in interface member definition: %+A" tupleType
|
| _ -> failwithf "Didn't have alternating type-and-star in interface member definition: %+A" tupleType
|
||||||
|
|
||||||
let toFun (inputs : SynType list) (ret : SynType) : SynType =
|
|
||||||
(ret, List.rev inputs)
|
|
||||||
||> List.fold (fun ty input -> SynType.CreateFun (input, ty))
|
|
||||||
|
|
||||||
/// Returns the args (where these are tuple types if curried) in order, and the return type.
|
/// Returns the args (where these are tuple types if curried) in order, and the return type.
|
||||||
let rec getType (ty : SynType) : (SynType * bool) list * SynType =
|
let rec getType (ty : SynType) : (SynType * bool) list * SynType =
|
||||||
match ty with
|
match ty with
|
||||||
@@ -269,7 +200,7 @@ module internal AstHelper =
|
|||||||
| SynType.Paren (argType, _) -> getType argType, true
|
| SynType.Paren (argType, _) -> getType argType, true
|
||||||
| _ -> getType argType, false
|
| _ -> getType argType, false
|
||||||
|
|
||||||
((toFun (List.map fst inputArgs) inputRet), hasParen) :: args, ret
|
((SynType.toFun (List.map fst inputArgs) inputRet), hasParen) :: args, ret
|
||||||
| _ -> [], ty
|
| _ -> [], ty
|
||||||
|
|
||||||
let private parseMember (slotSig : SynValSig) (flags : SynMemberFlags) : Choice<MemberInfo, PropertyInfo> =
|
let private parseMember (slotSig : SynValSig) (flags : SynMemberFlags) : Choice<MemberInfo, PropertyInfo> =
|
||||||
@@ -326,7 +257,7 @@ module internal AstHelper =
|
|||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent ident)
|
Type = SynType.createLongIdent ident
|
||||||
}
|
}
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
}
|
}
|
||||||
@@ -338,11 +269,22 @@ module internal AstHelper =
|
|||||||
Attributes = []
|
Attributes = []
|
||||||
IsOptional = false
|
IsOptional = false
|
||||||
Id = None
|
Id = None
|
||||||
Type = SynType.Var (typar, range0)
|
Type = SynType.var typar
|
||||||
|
}
|
||||||
|
|> List.singleton
|
||||||
|
}
|
||||||
|
| arg ->
|
||||||
|
{
|
||||||
|
HasParen = false
|
||||||
|
Args =
|
||||||
|
{
|
||||||
|
Attributes = []
|
||||||
|
IsOptional = false
|
||||||
|
Id = None
|
||||||
|
Type = arg
|
||||||
}
|
}
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
}
|
}
|
||||||
| _ -> failwith $"Unrecognised args in interface method declaration: %+A{args}"
|
|
||||||
|> fun ty ->
|
|> fun ty ->
|
||||||
{ ty with
|
{ ty with
|
||||||
HasParen = ty.HasParen || hasParen
|
HasParen = ty.HasParen || hasParen
|
||||||
@@ -386,22 +328,26 @@ module internal AstHelper =
|
|||||||
|
|
||||||
let attrs = attrs |> List.collect (fun s -> s.Attributes)
|
let attrs = attrs |> List.collect (fun s -> s.Attributes)
|
||||||
|
|
||||||
let members, properties =
|
let members, inherits =
|
||||||
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, _, _) -> parseMember slotSig flags
|
| SynMemberDefn.AbstractSlot (slotSig, flags, _, _) -> Choice1Of2 (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
|
||||||
@@ -477,176 +423,3 @@ module internal AstHelper =
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
| _ -> failwithf "Failed to get record elements for type that was: %+A" repr
|
| _ -> failwithf "Failed to get record elements for type that was: %+A" repr
|
||||||
|
|
||||||
[<AutoOpen>]
|
|
||||||
module internal SynTypePatterns =
|
|
||||||
let (|OptionType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isOptionIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|ListType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isListIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|ArrayType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isArrayIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| SynType.Array (1, innerType, _) -> Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|RestEaseResponseType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isResponseIdent ident ->
|
|
||||||
Some innerType
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|DictionaryType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isDictionaryIdent ident ->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|IDictionaryType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isIDictionaryIdent ident ->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|IReadOnlyDictionaryType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when
|
|
||||||
AstHelper.isReadOnlyDictionaryIdent ident
|
|
||||||
->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|MapType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isMapIdent ident ->
|
|
||||||
Some (key, value)
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
/// 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" ; "bool" ; "char" ]
|
|
||||||
|> List.tryFind (fun s -> s = i.idText)
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|String|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] ->
|
|
||||||
[ "string" ]
|
|
||||||
|> List.tryFind (fun s -> s = i.idText)
|
|
||||||
|> Option.map ignore<string>
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Byte|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] -> [ "byte" ] |> List.tryFind (fun s -> s = i.idText) |> Option.map ignore<string>
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Guid|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Guid" ]
|
|
||||||
| [ "Guid" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|HttpResponseMessage|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Net" ; "Http" ; "HttpResponseMessage" ]
|
|
||||||
| [ "Net" ; "Http" ; "HttpResponseMessage" ]
|
|
||||||
| [ "Http" ; "HttpResponseMessage" ]
|
|
||||||
| [ "HttpResponseMessage" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|HttpContent|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Net" ; "Http" ; "HttpContent" ]
|
|
||||||
| [ "Net" ; "Http" ; "HttpContent" ]
|
|
||||||
| [ "Http" ; "HttpContent" ]
|
|
||||||
| [ "HttpContent" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Stream|_|) (fieldType : SynType) : unit option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "IO" ; "Stream" ]
|
|
||||||
| [ "IO" ; "Stream" ]
|
|
||||||
| [ "Stream" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|NumberType|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent ident ->
|
|
||||||
match ident.LongIdent with
|
|
||||||
| [ i ] -> [ "string" ; "float" ; "int" ; "bool" ] |> List.tryFind (fun s -> s = i.idText)
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|DateOnly|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "DateOnly" ]
|
|
||||||
| [ "DateOnly" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|DateTime|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "DateTime" ]
|
|
||||||
| [ "DateTime" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Uri|_|) (fieldType : SynType) =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "System" ; "Uri" ]
|
|
||||||
| [ "Uri" ] -> Some ()
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let (|Task|_|) (fieldType : SynType) : SynType option =
|
|
||||||
match fieldType with
|
|
||||||
| SynType.App (SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)), _, args, _, _, _, _) ->
|
|
||||||
match ident |> List.map (fun i -> i.idText) with
|
|
||||||
| [ "Task" ]
|
|
||||||
| [ "Tasks" ; "Task" ]
|
|
||||||
| [ "Threading" ; "Tasks" ; "Task" ]
|
|
||||||
| [ "System" ; "Threading" ; "Tasks" ; "Task" ] ->
|
|
||||||
match args with
|
|
||||||
| [ arg ] -> Some arg
|
|
||||||
| _ -> failwithf "Expected Task to be applied to exactly one arg, but got: %+A" args
|
|
||||||
| _ -> None
|
|
||||||
| _ -> None
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,7 @@ namespace WoofWare.Myriad.Plugins
|
|||||||
|
|
||||||
open System
|
open System
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Fantomas.FCS.Xml
|
open Fantomas.FCS.Xml
|
||||||
open Myriad.Core
|
|
||||||
|
|
||||||
type internal GenerateMockOutputSpec =
|
type internal GenerateMockOutputSpec =
|
||||||
{
|
{
|
||||||
@@ -14,13 +12,15 @@ type internal GenerateMockOutputSpec =
|
|||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal InterfaceMockGenerator =
|
module internal InterfaceMockGenerator =
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
open Myriad.Core.Ast
|
|
||||||
|
|
||||||
let private getName (SynField (_, _, id, _, _, _, _, _, _)) =
|
let private getName (SynField (_, _, id, _, _, _, _, _, _)) =
|
||||||
match id with
|
match id with
|
||||||
| 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)
|
||||||
@@ -29,157 +29,106 @@ module internal InterfaceMockGenerator =
|
|||||||
(fields : SynField list)
|
(fields : SynField list)
|
||||||
: SynModuleDecl
|
: SynModuleDecl
|
||||||
=
|
=
|
||||||
let synValData =
|
let inherits =
|
||||||
{
|
interfaceType.Inherits
|
||||||
SynMemberFlags.IsInstance = false
|
|> Seq.map (fun ty ->
|
||||||
SynMemberFlags.IsDispatchSlot = false
|
match ty with
|
||||||
SynMemberFlags.IsOverrideOrExplicitImpl = false
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (name, _, _)) ->
|
||||||
SynMemberFlags.IsFinal = false
|
match name |> List.map _.idText with
|
||||||
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
| [] -> failwith "Unexpected empty identifier in inheritance declaration"
|
||||||
SynMemberFlags.MemberKind = SynMemberKind.Member
|
| [ "IDisposable" ]
|
||||||
}
|
| [ "System" ; "IDisposable" ] -> KnownInheritance.IDisposable
|
||||||
|
| _ -> failwithf "Unrecognised inheritance identifier: %+A" name
|
||||||
let failwithFun =
|
| x -> failwithf "Unrecognised type in inheritance: %+A" x
|
||||||
SynExpr.createLambda
|
|
||||||
"x"
|
|
||||||
(SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateIdentString "raise",
|
|
||||||
SynExpr.CreateParen (
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "NotImplementedException" ]),
|
|
||||||
SynExpr.CreateConstString "Unimplemented mock function"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
let constructorIdent =
|
|
||||||
let generics =
|
|
||||||
interfaceType.Generics
|
|
||||||
|> Option.map (fun generics -> SynValTyparDecls (Some generics, false))
|
|
||||||
|
|
||||||
SynPat.LongIdent (
|
|
||||||
SynLongIdent.CreateString "Empty",
|
|
||||||
None,
|
|
||||||
None, // no generics on the "Empty", only on the return type
|
|
||||||
SynArgPats.Pats (
|
|
||||||
if generics.IsNone then
|
|
||||||
[]
|
|
||||||
else
|
|
||||||
[ SynPat.CreateParen (SynPat.CreateConst SynConst.Unit) ]
|
|
||||||
),
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
)
|
)
|
||||||
|
|> Set.ofSeq
|
||||||
|
|
||||||
|
let failwithFun (SynField (_, _, idOpt, _, _, _, _, _, _)) =
|
||||||
|
let failString =
|
||||||
|
match idOpt with
|
||||||
|
| None -> SynExpr.CreateConst "Unimplemented mock function"
|
||||||
|
| Some ident -> SynExpr.CreateConst $"Unimplemented mock function: %s{ident.idText}"
|
||||||
|
|
||||||
|
SynExpr.createLongIdent [ "System" ; "NotImplementedException" ]
|
||||||
|
|> SynExpr.applyTo failString
|
||||||
|
|> SynExpr.paren
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||||
|
|> SynExpr.createLambda "_"
|
||||||
|
|
||||||
let constructorReturnType =
|
let constructorReturnType =
|
||||||
match interfaceType.Generics with
|
match interfaceType.Generics with
|
||||||
| None -> SynType.CreateLongIdent name
|
| None -> SynType.createLongIdent' [ name ]
|
||||||
| Some generics ->
|
| Some generics ->
|
||||||
let generics =
|
|
||||||
generics.TyparDecls
|
|
||||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|
|
||||||
|
|
||||||
SynType.App (
|
let generics =
|
||||||
SynType.CreateLongIdent name,
|
generics.TyparDecls
|
||||||
Some range0,
|
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||||
generics,
|
|
||||||
List.replicate (generics.Length - 1) range0,
|
SynType.app name generics
|
||||||
Some range0,
|
|
||||||
false,
|
let constructorFields =
|
||||||
range0
|
let extras =
|
||||||
)
|
if inherits.Contains KnownInheritance.IDisposable then
|
||||||
|> SynBindingReturnInfo.Create
|
let unitFun = SynExpr.createThunk (SynExpr.CreateConst ())
|
||||||
|
|
||||||
|
[ (SynLongIdent.createS "Dispose", true), Some unitFun ]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
|
||||||
|
let nonExtras =
|
||||||
|
fields
|
||||||
|
|> List.map (fun field -> (SynLongIdent.createI (getName field), true), Some (failwithFun field))
|
||||||
|
|
||||||
|
extras @ nonExtras
|
||||||
|
|
||||||
let constructor =
|
let constructor =
|
||||||
SynMemberDefn.Member (
|
SynBinding.basic
|
||||||
SynBinding.SynBinding (
|
[ Ident.create "Empty" ]
|
||||||
None,
|
(if interfaceType.Generics.IsNone then
|
||||||
SynBindingKind.Normal,
|
[]
|
||||||
false,
|
else
|
||||||
false,
|
[ SynPat.unit ])
|
||||||
[],
|
(AstHelper.instantiateRecord constructorFields)
|
||||||
PreXmlDoc.Create " An implementation where every method throws.",
|
|> SynBinding.withXmlDoc (PreXmlDoc.create "An implementation where every method throws.")
|
||||||
SynValData.SynValData (Some synValData, SynValInfo.Empty, None),
|
|> SynBinding.withReturnAnnotation constructorReturnType
|
||||||
constructorIdent,
|
|> SynMemberDefn.staticMember
|
||||||
Some constructorReturnType,
|
|
||||||
AstHelper.instantiateRecord (
|
let fields =
|
||||||
fields
|
let extras =
|
||||||
|> List.map (fun field ->
|
if inherits.Contains KnownInheritance.IDisposable then
|
||||||
((SynLongIdent.CreateFromLongIdent [ getName field ], true), Some failwithFun)
|
{
|
||||||
)
|
Attrs = []
|
||||||
),
|
Ident = Some (Ident.create "Dispose")
|
||||||
range0,
|
Type = SynType.funFromDomain SynType.unit SynType.unit
|
||||||
DebugPointAtBinding.Yes range0,
|
|
||||||
{ SynExpr.synBindingTriviaZero true with
|
|
||||||
LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0)
|
|
||||||
}
|
}
|
||||||
),
|
|> SynField.make
|
||||||
range0
|
|> SynField.withDocString (PreXmlDoc.create "Implementation of IDisposable.Dispose")
|
||||||
)
|
|> List.singleton
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
|
||||||
|
extras @ fields
|
||||||
|
|
||||||
let interfaceMembers =
|
let interfaceMembers =
|
||||||
let members =
|
let members =
|
||||||
interfaceType.Members
|
interfaceType.Members
|
||||||
|> List.map (fun memberInfo ->
|
|> List.map (fun memberInfo ->
|
||||||
|
|
||||||
let synValData =
|
|
||||||
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
|
|
||||||
)
|
|
||||||
]
|
|
||||||
yield!
|
|
||||||
memberInfo.Args
|
|
||||||
|> List.mapi (fun i arg ->
|
|
||||||
arg.Args
|
|
||||||
|> List.mapi (fun j arg ->
|
|
||||||
SynArgInfo.CreateIdString $"arg_%i{i}_%i{j}"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
returnInfo =
|
|
||||||
SynArgInfo.SynArgInfo (attributes = [], optional = false, ident = None)
|
|
||||||
),
|
|
||||||
thisIdOpt = None
|
|
||||||
)
|
|
||||||
|
|
||||||
let headArgs =
|
let headArgs =
|
||||||
memberInfo.Args
|
memberInfo.Args
|
||||||
|> List.mapi (fun i tupledArgs ->
|
|> List.mapi (fun i tupledArgs ->
|
||||||
let args =
|
let args =
|
||||||
tupledArgs.Args
|
tupledArgs.Args
|
||||||
|> List.mapi (fun j _ -> SynPat.CreateNamed (Ident.Create $"arg_%i{i}_%i{j}"))
|
|> List.mapi (fun j ty ->
|
||||||
|
match ty.Type with
|
||||||
|
| UnitType -> SynPat.unit
|
||||||
|
| _ -> SynPat.named $"arg_%i{i}_%i{j}"
|
||||||
|
)
|
||||||
|
|
||||||
SynPat.Tuple (false, args, List.replicate (args.Length - 1) range0, range0)
|
match args with
|
||||||
|> SynPat.CreateParen
|
| [] -> failwith "somehow got no args at all"
|
||||||
|> fun i -> if tupledArgs.HasParen then SynPat.Paren (i, range0) else i
|
| [ arg ] -> arg
|
||||||
)
|
| args -> SynPat.tuple args
|
||||||
|
|> fun i -> if tupledArgs.HasParen then SynPat.paren i else i
|
||||||
let headPat =
|
|
||||||
SynPat.LongIdent (
|
|
||||||
SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; memberInfo.Identifier ],
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
SynArgPats.Pats headArgs,
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let body =
|
let body =
|
||||||
@@ -187,8 +136,12 @@ 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 args -> SynExpr.CreateIdentString $"arg_%i{i}_%i{j}")
|
|> List.mapi (fun j arg ->
|
||||||
|> SynExpr.CreateParenedTuple
|
match arg.Type with
|
||||||
|
| UnitType -> SynExpr.CreateConst ()
|
||||||
|
| _ -> SynExpr.createIdent $"arg_%i{i}_%i{j}"
|
||||||
|
)
|
||||||
|
|> SynExpr.tuple
|
||||||
)
|
)
|
||||||
|
|
||||||
match tuples |> List.rev with
|
match tuples |> List.rev with
|
||||||
@@ -196,42 +149,17 @@ module internal InterfaceMockGenerator =
|
|||||||
| last :: rest ->
|
| last :: rest ->
|
||||||
|
|
||||||
(last, rest)
|
(last, rest)
|
||||||
||> List.fold (fun trail next -> SynExpr.CreateApp (next, trail))
|
||> List.fold SynExpr.applyTo
|
||||||
|> fun args ->
|
|> SynExpr.applyFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.createLongIdent' [ Ident.create "this" ; memberInfo.Identifier ]
|
||||||
SynExpr.CreateLongIdent (
|
)
|
||||||
SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; memberInfo.Identifier ]
|
|
||||||
),
|
|
||||||
args
|
|
||||||
)
|
|
||||||
|
|
||||||
SynMemberDefn.Member (
|
SynBinding.basic [ Ident.create "this" ; memberInfo.Identifier ] headArgs body
|
||||||
SynBinding.SynBinding (
|
|> SynMemberDefn.memberImplementation
|
||||||
None,
|
|
||||||
SynBindingKind.Normal,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[],
|
|
||||||
PreXmlDoc.Empty,
|
|
||||||
synValData,
|
|
||||||
headPat,
|
|
||||||
None,
|
|
||||||
body,
|
|
||||||
range0,
|
|
||||||
DebugPointAtBinding.Yes range0,
|
|
||||||
{
|
|
||||||
LeadingKeyword = SynLeadingKeyword.Member range0
|
|
||||||
InlineKeyword = None
|
|
||||||
EqualsRange = Some range0
|
|
||||||
}
|
|
||||||
),
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let interfaceName =
|
let interfaceName =
|
||||||
let baseName =
|
let baseName = SynType.createLongIdent interfaceType.Name
|
||||||
SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name)
|
|
||||||
|
|
||||||
match interfaceType.Generics with
|
match interfaceType.Generics with
|
||||||
| None -> baseName
|
| None -> baseName
|
||||||
@@ -241,17 +169,9 @@ module internal InterfaceMockGenerator =
|
|||||||
| SynTyparDecls.PostfixList (decls, _, _) -> decls
|
| SynTyparDecls.PostfixList (decls, _, _) -> decls
|
||||||
| SynTyparDecls.PrefixList (decls, _) -> decls
|
| SynTyparDecls.PrefixList (decls, _) -> decls
|
||||||
| SynTyparDecls.SinglePrefix (decl, _) -> [ decl ]
|
| SynTyparDecls.SinglePrefix (decl, _) -> [ decl ]
|
||||||
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0))
|
|> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar)
|
||||||
|
|
||||||
SynType.App (
|
SynType.app' baseName generics
|
||||||
baseName,
|
|
||||||
Some range0,
|
|
||||||
generics,
|
|
||||||
List.replicate (generics.Length - 1) range0,
|
|
||||||
Some range0,
|
|
||||||
false,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
||||||
|
|
||||||
@@ -264,11 +184,32 @@ 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 mem =
|
||||||
|
SynExpr.createLongIdent [ "this" ; "Dispose" ]
|
||||||
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
|
|> SynBinding.basic [ Ident.create "this" ; Ident.create "Dispose" ] [ SynPat.unit ]
|
||||||
|
|> SynBinding.withReturnAnnotation SynType.unit
|
||||||
|
|> SynMemberDefn.memberImplementation
|
||||||
|
|
||||||
|
SynMemberDefn.Interface (
|
||||||
|
SynType.createLongIdent' [ "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 ]
|
Members = Some ([ constructor ; interfaceMembers ] @ extraInterfaces)
|
||||||
XmlDoc = Some xmlDoc
|
XmlDoc = Some xmlDoc
|
||||||
Generics = interfaceType.Generics
|
Generics = interfaceType.Generics
|
||||||
Accessibility = Some access
|
Accessibility = Some access
|
||||||
@@ -280,7 +221,7 @@ module internal InterfaceMockGenerator =
|
|||||||
|
|
||||||
let private buildType (x : ParameterInfo) : SynType =
|
let private buildType (x : ParameterInfo) : SynType =
|
||||||
if x.IsOptional then
|
if x.IsOptional then
|
||||||
SynType.App (SynType.CreateLongIdent "option", Some range0, [ x.Type ], [], Some range0, false, range0)
|
SynType.app "option" [ x.Type ]
|
||||||
else
|
else
|
||||||
x.Type
|
x.Type
|
||||||
|
|
||||||
@@ -297,19 +238,15 @@ module internal InterfaceMockGenerator =
|
|||||||
let constructMember (mem : MemberInfo) : SynField =
|
let constructMember (mem : MemberInfo) : SynField =
|
||||||
let inputType = mem.Args |> List.map constructMemberSinglePlace
|
let inputType = mem.Args |> List.map constructMemberSinglePlace
|
||||||
|
|
||||||
let funcType = AstHelper.toFun inputType mem.ReturnType
|
let funcType = SynType.toFun inputType mem.ReturnType
|
||||||
|
|
||||||
SynField.SynField (
|
{
|
||||||
[],
|
Type = funcType
|
||||||
false,
|
Attrs = []
|
||||||
Some mem.Identifier,
|
Ident = Some mem.Identifier
|
||||||
funcType,
|
}
|
||||||
false,
|
|> SynField.make
|
||||||
mem.XmlDoc |> Option.defaultValue PreXmlDoc.Empty,
|
|> SynField.withDocString (mem.XmlDoc |> Option.defaultValue PreXmlDoc.Empty)
|
||||||
None,
|
|
||||||
range0,
|
|
||||||
SynFieldTrivia.Zero
|
|
||||||
)
|
|
||||||
|
|
||||||
let createRecord
|
let createRecord
|
||||||
(namespaceId : LongIdent)
|
(namespaceId : LongIdent)
|
||||||
@@ -319,25 +256,24 @@ module internal InterfaceMockGenerator =
|
|||||||
=
|
=
|
||||||
let interfaceType = AstHelper.parseInterface interfaceType
|
let interfaceType = AstHelper.parseInterface interfaceType
|
||||||
let fields = interfaceType.Members |> List.map constructMember
|
let fields = interfaceType.Members |> List.map constructMember
|
||||||
let docString = PreXmlDoc.Create " Mock record type for an interface"
|
let docString = PreXmlDoc.create "Mock record type for an interface"
|
||||||
|
|
||||||
let name =
|
let name =
|
||||||
List.last interfaceType.Name
|
List.last interfaceType.Name
|
||||||
|> _.idText
|
|> _.idText
|
||||||
|> fun s ->
|
|> fun s ->
|
||||||
if s.StartsWith 'I' && s.Length > 1 && Char.IsUpper s.[1] then
|
if s.StartsWith 'I' && s.Length > 1 && Char.IsUpper s.[1] then
|
||||||
s.[1..]
|
s.Substring 1
|
||||||
else
|
else
|
||||||
s
|
s
|
||||||
|> fun s -> s + "Mock"
|
|> fun s -> s + "Mock"
|
||||||
|
|
||||||
let typeDecl = createType spec name interfaceType docString fields
|
let typeDecl = createType spec name interfaceType docString fields
|
||||||
|
|
||||||
|
[ yield! opens |> List.map SynModuleDecl.openAny ; yield typeDecl ]
|
||||||
|
|> SynModuleOrNamespace.createNamespace namespaceId
|
||||||
|
|
||||||
SynModuleOrNamespace.CreateNamespace (
|
open Myriad.Core
|
||||||
namespaceId,
|
|
||||||
decls = (opens |> List.map SynModuleDecl.CreateOpen) @ [ typeDecl ]
|
|
||||||
)
|
|
||||||
|
|
||||||
/// Myriad generator that creates a record which implements the given interface,
|
/// Myriad generator that creates a record which implements the given interface,
|
||||||
/// but with every field mocked out.
|
/// but with every field mocked out.
|
||||||
|
@@ -4,8 +4,6 @@ open System
|
|||||||
open System.Text
|
open System.Text
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
open Fantomas.FCS.Xml
|
|
||||||
open Myriad.Core
|
|
||||||
|
|
||||||
type internal JsonParseOutputSpec =
|
type internal JsonParseOutputSpec =
|
||||||
{
|
{
|
||||||
@@ -15,7 +13,6 @@ type internal JsonParseOutputSpec =
|
|||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal JsonParseGenerator =
|
module internal JsonParseGenerator =
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
open Myriad.Core.Ast
|
|
||||||
|
|
||||||
type JsonParseOption =
|
type JsonParseOption =
|
||||||
{
|
{
|
||||||
@@ -30,38 +27,34 @@ module internal JsonParseGenerator =
|
|||||||
/// (match {indexed} with | null -> raise (System.Collections.Generic.KeyNotFoundException ()) | v -> v)
|
/// (match {indexed} with | null -> raise (System.Collections.Generic.KeyNotFoundException ()) | v -> v)
|
||||||
let assertNotNull (propertyName : SynExpr) (indexed : SynExpr) =
|
let assertNotNull (propertyName : SynExpr) (indexed : SynExpr) =
|
||||||
let raiseExpr =
|
let raiseExpr =
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateIdentString "raise",
|
(SynExpr.createIdent "sprintf")
|
||||||
SynExpr.CreateParen (
|
(SynExpr.CreateConst "Required key '%s' not found on JSON object")
|
||||||
SynExpr.CreateApp (
|
|> SynExpr.applyTo (SynExpr.paren propertyName)
|
||||||
SynExpr.CreateLongIdent (
|
|> SynExpr.paren
|
||||||
SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ]
|
|> SynExpr.applyFunction (
|
||||||
),
|
SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ]
|
||||||
SynExpr.CreateParen (
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateIdentString "sprintf",
|
|
||||||
SynExpr.CreateConstString "Required key '%s' not found on JSON object"
|
|
||||||
),
|
|
||||||
SynExpr.CreateParen propertyName
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|> SynExpr.paren
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createIdent "raise")
|
||||||
|
|
||||||
SynExpr.CreateMatch (
|
[
|
||||||
indexed,
|
SynMatchClause.create SynPat.createNull raiseExpr
|
||||||
[
|
SynMatchClause.create (SynPat.named "v") (SynExpr.createIdent "v")
|
||||||
SynMatchClause.Create (SynPat.CreateNull, None, raiseExpr)
|
]
|
||||||
SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, SynExpr.CreateIdentString "v")
|
|> SynExpr.createMatch indexed
|
||||||
]
|
|> SynExpr.paren
|
||||||
)
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|
|
||||||
/// {node}.AsValue().GetValue<{typeName}> ()
|
/// {node}.AsValue().GetValue<{typeName}> ()
|
||||||
/// If `propertyName` is Some, uses `assertNotNull {node}` instead of `{node}`.
|
/// If `propertyName` is Some, uses `assertNotNull {node}` instead of `{node}`.
|
||||||
let asValueGetValue (propertyName : SynExpr option) (typeName : string) (node : SynExpr) : SynExpr =
|
let asValueGetValue (propertyName : SynExpr option) (typeName : string) (node : SynExpr) : SynExpr =
|
||||||
|
match propertyName with
|
||||||
|
| None -> node
|
||||||
|
| Some propertyName -> assertNotNull propertyName node
|
||||||
|
|> SynExpr.callMethod "AsValue"
|
||||||
|
|> SynExpr.callGenericMethod' "GetValue" typeName
|
||||||
|
|
||||||
|
let asValueGetValueIdent (propertyName : SynExpr option) (typeName : LongIdent) (node : SynExpr) : SynExpr =
|
||||||
match propertyName with
|
match propertyName with
|
||||||
| None -> node
|
| None -> node
|
||||||
| Some propertyName -> assertNotNull propertyName node
|
| Some propertyName -> assertNotNull propertyName node
|
||||||
@@ -78,10 +71,8 @@ module internal JsonParseGenerator =
|
|||||||
|
|
||||||
/// {type}.jsonParse {node}
|
/// {type}.jsonParse {node}
|
||||||
let typeJsonParse (typeName : LongIdent) (node : SynExpr) : SynExpr =
|
let typeJsonParse (typeName : LongIdent) (node : SynExpr) : SynExpr =
|
||||||
SynExpr.CreateApp (
|
node
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (typeName @ [ Ident.Create "jsonParse" ])),
|
|> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ Ident.create "jsonParse" ]))
|
||||||
node
|
|
||||||
)
|
|
||||||
|
|
||||||
/// collectionType is e.g. "List"; we'll be calling `ofSeq` on it.
|
/// collectionType is e.g. "List"; we'll be calling `ofSeq` on it.
|
||||||
/// body is the body of a lambda which takes a parameter `elt`.
|
/// body is the body of a lambda which takes a parameter `elt`.
|
||||||
@@ -100,64 +91,41 @@ module internal JsonParseGenerator =
|
|||||||
| Some propertyName -> assertNotNull propertyName node
|
| Some propertyName -> assertNotNull propertyName node
|
||||||
|> SynExpr.callMethod "AsArray"
|
|> SynExpr.callMethod "AsArray"
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction (SynExpr.createLongIdent [ "Seq" ; "map" ]) (SynExpr.createLambda "elt" body)
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
|
||||||
SynExpr.createLambda "elt" body
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ collectionType ; "ofSeq" ]))
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ collectionType ; "ofSeq" ])
|
||||||
|
|
||||||
/// match {node} with | null -> None | v -> {body} |> Some
|
/// match {node} with | null -> None | v -> {body} |> Some
|
||||||
/// Use the variable `v` to get access to the `Some`.
|
/// Use the variable `v` to get access to the `Some`.
|
||||||
let createParseLineOption (node : SynExpr) (body : SynExpr) : SynExpr =
|
let createParseLineOption (node : SynExpr) (body : SynExpr) : SynExpr =
|
||||||
let body = SynExpr.pipeThroughFunction (SynExpr.CreateIdentString "Some") body
|
let body = SynExpr.pipeThroughFunction (SynExpr.createIdent "Some") body
|
||||||
|
|
||||||
SynExpr.CreateMatch (
|
[
|
||||||
node,
|
SynMatchClause.create SynPat.createNull (SynExpr.createIdent "None")
|
||||||
[
|
SynMatchClause.create (SynPat.named "v") body
|
||||||
SynMatchClause.Create (SynPat.CreateNull, None, SynExpr.CreateIdent (Ident.Create "None"))
|
]
|
||||||
SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, body)
|
|> SynExpr.createMatch node
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
/// Given e.g. "float", returns "System.Double.Parse"
|
/// Given e.g. "float", returns "System.Double.Parse"
|
||||||
let parseFunction (typeName : string) : LongIdent =
|
let parseFunction (typeName : string) : LongIdent =
|
||||||
List.append (SynExpr.qualifyPrimitiveType typeName) [ Ident.Create "Parse" ]
|
let qualified =
|
||||||
|
match Primitives.qualifyType typeName with
|
||||||
|
| Some x -> x
|
||||||
|
| None -> failwith $"Could not recognise type %s{typeName} as a primitive."
|
||||||
|
|
||||||
|
List.append qualified [ Ident.create "Parse" ]
|
||||||
|
|
||||||
/// fun kvp -> let key = {key(kvp)} in let value = {value(kvp)} in (key, value))
|
/// fun kvp -> let key = {key(kvp)} in let value = {value(kvp)} in (key, value))
|
||||||
/// The inputs will be fed with appropriate SynExprs to apply them to the `kvp.Key` and `kvp.Value` args.
|
/// The inputs will be fed with appropriate SynExprs to apply them to the `kvp.Key` and `kvp.Value` args.
|
||||||
let dictionaryMapper (key : SynExpr -> SynExpr) (value : SynExpr -> SynExpr) : SynExpr =
|
let dictionaryMapper (key : SynExpr -> SynExpr) (value : SynExpr -> SynExpr) : SynExpr =
|
||||||
let keyArg =
|
let keyArg = SynExpr.createLongIdent [ "kvp" ; "Key" ] |> SynExpr.paren
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "kvp" ; "Key" ])
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|
|
||||||
let valueArg =
|
let valueArg = SynExpr.createLongIdent [ "kvp" ; "Value" ] |> SynExpr.paren
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "kvp" ; "Value" ])
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|
|
||||||
SynExpr.LetOrUse (
|
// No need to paren here, we're on the LHS of a `let`
|
||||||
false,
|
SynExpr.tupleNoParen [ SynExpr.createIdent "key" ; SynExpr.createIdent "value" ]
|
||||||
false,
|
|> SynExpr.createLet [ SynBinding.basic [ Ident.create "value" ] [] (value valueArg) ]
|
||||||
[
|
|> SynExpr.createLet [ SynBinding.basic [ Ident.create "key" ] [] (key keyArg) ]
|
||||||
SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create "key"), expr = key keyArg)
|
|
||||||
],
|
|
||||||
SynExpr.LetOrUse (
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[
|
|
||||||
SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create "value"), expr = value valueArg)
|
|
||||||
],
|
|
||||||
SynExpr.CreateTuple [ SynExpr.CreateIdentString "key" ; SynExpr.CreateIdentString "value" ],
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
InKeyword = None
|
|
||||||
}
|
|
||||||
),
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
InKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|> SynExpr.createLambda "kvp"
|
|> SynExpr.createLambda "kvp"
|
||||||
|
|
||||||
/// A conforming JSON object has only strings as keys. But it would be reasonable to allow the user
|
/// A conforming JSON object has only strings as keys. But it would be reasonable to allow the user
|
||||||
@@ -167,7 +135,7 @@ module internal JsonParseGenerator =
|
|||||||
| String -> key
|
| String -> key
|
||||||
| Uri ->
|
| Uri ->
|
||||||
key
|
key
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ]))
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Uri" ])
|
||||||
| _ ->
|
| _ ->
|
||||||
failwithf
|
failwithf
|
||||||
$"Unable to parse the key type %+A{desiredType} of a JSON object. Keys are strings, and this plugin does not know how to convert to that from a string."
|
$"Unable to parse the key type %+A{desiredType} of a JSON object. Keys are strings, and this plugin does not know how to convert to that from a string."
|
||||||
@@ -187,25 +155,19 @@ module internal JsonParseGenerator =
|
|||||||
| DateOnly ->
|
| DateOnly ->
|
||||||
node
|
node
|
||||||
|> asValueGetValue propertyName "string"
|
|> asValueGetValue propertyName "string"
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "DateOnly" ; "Parse" ])
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "DateOnly" ; "Parse" ])
|
|
||||||
)
|
|
||||||
| Uri ->
|
| Uri ->
|
||||||
node
|
node
|
||||||
|> asValueGetValue propertyName "string"
|
|> asValueGetValue propertyName "string"
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ]))
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Uri" ])
|
||||||
| Guid ->
|
| Guid ->
|
||||||
node
|
node
|
||||||
|> asValueGetValue propertyName "string"
|
|> asValueGetValue propertyName "string"
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Guid" ; "Parse" ])
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Guid" ; "Parse" ])
|
|
||||||
)
|
|
||||||
| DateTime ->
|
| DateTime ->
|
||||||
node
|
node
|
||||||
|> asValueGetValue propertyName "string"
|
|> asValueGetValue propertyName "string"
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "DateTime" ; "Parse" ])
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "DateTime" ; "Parse" ])
|
|
||||||
)
|
|
||||||
| NumberType typeName ->
|
| NumberType typeName ->
|
||||||
let basic = asValueGetValue propertyName typeName node
|
let basic = asValueGetValue propertyName typeName node
|
||||||
|
|
||||||
@@ -213,105 +175,92 @@ module internal JsonParseGenerator =
|
|||||||
| None -> basic
|
| None -> basic
|
||||||
| Some option ->
|
| Some option ->
|
||||||
let cond =
|
let cond =
|
||||||
SynExpr.DotGet (
|
SynExpr.DotGet (SynExpr.createIdent "exc", range0, SynLongIdent.createS "Message", range0)
|
||||||
SynExpr.CreateIdentString "exc",
|
|> SynExpr.callMethodArg "Contains" (SynExpr.CreateConst "cannot be converted to")
|
||||||
range0,
|
|
||||||
SynLongIdent.CreateString "Message",
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|> SynExpr.callMethodArg
|
|
||||||
"Contains"
|
|
||||||
(SynExpr.CreateConst (SynConst.CreateString "cannot be converted to"))
|
|
||||||
|
|
||||||
let handler =
|
let handler =
|
||||||
asValueGetValue propertyName "string" node
|
asValueGetValue propertyName "string" node
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent' (parseFunction typeName))
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (parseFunction typeName))
|
|
||||||
)
|
|
||||||
|> SynExpr.ifThenElse
|
|> SynExpr.ifThenElse
|
||||||
(SynExpr.equals
|
(SynExpr.equals
|
||||||
option
|
option
|
||||||
(SynExpr.CreateLongIdent (
|
(SynExpr.createLongIdent
|
||||||
SynLongIdent.Create
|
[
|
||||||
[
|
"System"
|
||||||
"System"
|
"Text"
|
||||||
"Text"
|
"Json"
|
||||||
"Json"
|
"Serialization"
|
||||||
"Serialization"
|
"JsonNumberHandling"
|
||||||
"JsonNumberHandling"
|
"AllowReadingFromString"
|
||||||
"AllowReadingFromString"
|
]))
|
||||||
]
|
|
||||||
)))
|
|
||||||
SynExpr.reraise
|
SynExpr.reraise
|
||||||
|> SynExpr.ifThenElse cond SynExpr.reraise
|
|> SynExpr.ifThenElse cond SynExpr.reraise
|
||||||
|
|
||||||
basic
|
basic
|
||||||
|> SynExpr.pipeThroughTryWith
|
|> SynExpr.pipeThroughTryWith
|
||||||
(SynPat.IsInst (
|
(SynPat.IsInst (
|
||||||
SynType.LongIdent (SynLongIdent.Create [ "System" ; "InvalidOperationException" ]),
|
SynType.LongIdent (SynLongIdent.createS' [ "System" ; "InvalidOperationException" ]),
|
||||||
range0
|
range0
|
||||||
))
|
))
|
||||||
handler
|
handler
|
||||||
| PrimitiveType typeName -> asValueGetValue propertyName typeName node
|
| PrimitiveType typeName -> asValueGetValueIdent propertyName typeName node
|
||||||
| OptionType ty ->
|
| OptionType ty ->
|
||||||
parseNode None options ty (SynExpr.CreateIdentString "v")
|
parseNode None options ty (SynExpr.createIdent "v")
|
||||||
|> createParseLineOption node
|
|> createParseLineOption node
|
||||||
| ListType ty ->
|
| ListType ty ->
|
||||||
parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"))
|
parseNode None options ty (SynExpr.createIdent "elt")
|
||||||
|> asArrayMapped propertyName "List" node
|
|> asArrayMapped propertyName "List" node
|
||||||
| ArrayType ty ->
|
| ArrayType ty ->
|
||||||
parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt"))
|
parseNode None options ty (SynExpr.createIdent "elt")
|
||||||
|> asArrayMapped propertyName "Array" node
|
|> asArrayMapped propertyName "Array" node
|
||||||
| IDictionaryType (keyType, valueType) ->
|
| IDictionaryType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "dict" ]))
|
|> SynExpr.pipeThroughFunction (SynExpr.createIdent "dict")
|
||||||
| DictionaryType (keyType, valueType) ->
|
| DictionaryType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
SynExpr.CreateLongIdent (
|
(SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ])
|
||||||
SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "Dictionary" ])
|
SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "Dictionary" ]
|
||||||
)
|
)
|
||||||
| IReadOnlyDictionaryType (keyType, valueType) ->
|
| IReadOnlyDictionaryType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "readOnlyDict" ]))
|
|> SynExpr.pipeThroughFunction (SynExpr.createIdent "readOnlyDict")
|
||||||
| MapType (keyType, valueType) ->
|
| MapType (keyType, valueType) ->
|
||||||
node
|
node
|
||||||
|> asObject propertyName
|
|> asObject propertyName
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.CreateApp (
|
SynExpr.applyFunction
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]),
|
(SynExpr.createLongIdent [ "Seq" ; "map" ])
|
||||||
dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)
|
(dictionaryMapper (parseKeyString keyType) (parseNode None options valueType))
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Map" ; "ofSeq" ]))
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "Map" ; "ofSeq" ])
|
||||||
|
| BigInt ->
|
||||||
|
node
|
||||||
|
|> SynExpr.callMethod "ToJsonString"
|
||||||
|
|> SynExpr.paren
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "Numerics" ; "BigInteger" ; "Parse" ])
|
||||||
| _ ->
|
| _ ->
|
||||||
// Let's just hope that we've also got our own type annotation!
|
// Let's just hope that we've also got our own type annotation!
|
||||||
let typeName =
|
let typeName =
|
||||||
@@ -327,9 +276,8 @@ module internal JsonParseGenerator =
|
|||||||
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
||||||
/// The result of this function is the body of a let-binding (not including the LHS of that let-binding).
|
/// The result of this function is the body of a let-binding (not including the LHS of that let-binding).
|
||||||
let createParseRhs (options : JsonParseOption) (propertyName : SynExpr) (fieldType : SynType) : SynExpr =
|
let createParseRhs (options : JsonParseOption) (propertyName : SynExpr) (fieldType : SynType) : SynExpr =
|
||||||
SynExpr.CreateIdentString "node"
|
let objectToParse = SynExpr.createIdent "node" |> SynExpr.index propertyName
|
||||||
|> SynExpr.index propertyName
|
parseNode (Some propertyName) options fieldType objectToParse
|
||||||
|> parseNode (Some propertyName) options fieldType
|
|
||||||
|
|
||||||
let isJsonNumberHandling (literal : LongIdent) : bool =
|
let isJsonNumberHandling (literal : LongIdent) : bool =
|
||||||
match List.rev literal |> List.map (fun ident -> ident.idText) with
|
match List.rev literal |> List.map (fun ident -> ident.idText) with
|
||||||
@@ -340,270 +288,260 @@ module internal JsonParseGenerator =
|
|||||||
| [ _ ; "JsonNumberHandling" ; "Serialization" ; "Json" ; "Text" ; "System" ] -> true
|
| [ _ ; "JsonNumberHandling" ; "Serialization" ; "Json" ; "Text" ; "System" ] -> true
|
||||||
| _ -> false
|
| _ -> false
|
||||||
|
|
||||||
let createMaker (spec : JsonParseOutputSpec) (typeName : LongIdent) (fields : SynField list) =
|
/// `populateNode` will be inserted before we return the `node` variable.
|
||||||
let xmlDoc = PreXmlDoc.Create " Parse from a JSON node."
|
///
|
||||||
|
/// That is, we give you access to a `JsonNode` called `node`,
|
||||||
|
/// and you must return a `typeName`.
|
||||||
|
let scaffolding (spec : JsonParseOutputSpec) (typeName : LongIdent) (functionBody : SynExpr) : SynModuleDecl =
|
||||||
|
let xmlDoc = PreXmlDoc.create "Parse from a JSON node."
|
||||||
|
|
||||||
let returnInfo =
|
let returnInfo = SynType.createLongIdent typeName
|
||||||
SynBindingReturnInfo.Create (SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName))
|
|
||||||
|
|
||||||
let inputArg = Ident.Create "node"
|
let inputArg = "node"
|
||||||
let functionName = Ident.Create "jsonParse"
|
let functionName = Ident.create "jsonParse"
|
||||||
|
|
||||||
let inputVal =
|
let arg =
|
||||||
let memberFlags =
|
SynPat.named inputArg
|
||||||
if spec.ExtensionMethods then
|
|> SynPat.annotateType (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||||
{
|
|
||||||
SynMemberFlags.IsInstance = false
|
|
||||||
SynMemberFlags.IsDispatchSlot = false
|
|
||||||
SynMemberFlags.IsOverrideOrExplicitImpl = false
|
|
||||||
SynMemberFlags.IsFinal = false
|
|
||||||
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
|
||||||
SynMemberFlags.MemberKind = SynMemberKind.Member
|
|
||||||
}
|
|
||||||
|> Some
|
|
||||||
else
|
|
||||||
None
|
|
||||||
|
|
||||||
let thisIdOpt = if spec.ExtensionMethods then None else Some inputArg
|
if spec.ExtensionMethods then
|
||||||
|
let binding =
|
||||||
|
SynBinding.basic [ functionName ] [ arg ] functionBody
|
||||||
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|
|> SynMemberDefn.staticMember
|
||||||
|
|
||||||
SynValData.SynValData (
|
let componentInfo =
|
||||||
memberFlags,
|
SynComponentInfo.createLong typeName
|
||||||
SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty),
|
|> SynComponentInfo.withDocString (PreXmlDoc.create "Extension methods for JSON parsing")
|
||||||
thisIdOpt
|
|
||||||
)
|
|
||||||
|
|
||||||
|
let containingType =
|
||||||
|
SynTypeDefnRepr.augmentation ()
|
||||||
|
|> SynTypeDefn.create componentInfo
|
||||||
|
|> SynTypeDefn.withMemberDefns [ binding ]
|
||||||
|
|
||||||
|
SynModuleDecl.Types ([ containingType ], range0)
|
||||||
|
else
|
||||||
|
SynBinding.basic [ functionName ] [ arg ] functionBody
|
||||||
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|
|> SynModuleDecl.createLet
|
||||||
|
|
||||||
|
let getParseOptions (fieldAttrs : SynAttribute list) =
|
||||||
|
(JsonParseOption.None, fieldAttrs)
|
||||||
|
||> List.fold (fun options attr ->
|
||||||
|
if
|
||||||
|
(SynLongIdent.toString attr.TypeName)
|
||||||
|
.EndsWith ("JsonNumberHandling", StringComparison.Ordinal)
|
||||||
|
then
|
||||||
|
let qualifiedEnumValue =
|
||||||
|
match SynExpr.stripOptionalParen attr.ArgExpr with
|
||||||
|
| SynExpr.LongIdent (_, SynLongIdent (ident, _, _), _, _) when isJsonNumberHandling ident ->
|
||||||
|
// Make sure it's fully qualified
|
||||||
|
SynExpr.createLongIdent
|
||||||
|
[
|
||||||
|
"System"
|
||||||
|
"Text"
|
||||||
|
"Json"
|
||||||
|
"Serialization"
|
||||||
|
"JsonNumberHandling"
|
||||||
|
"AllowReadingFromString"
|
||||||
|
]
|
||||||
|
| _ -> attr.ArgExpr
|
||||||
|
|
||||||
|
{
|
||||||
|
JsonNumberHandlingArg = Some qualifiedEnumValue
|
||||||
|
}
|
||||||
|
else
|
||||||
|
options
|
||||||
|
)
|
||||||
|
|
||||||
|
let createRecordMaker (spec : JsonParseOutputSpec) (fields : SynFieldData<Ident> list) =
|
||||||
let assignments =
|
let assignments =
|
||||||
fields
|
fields
|
||||||
|> List.map (fun (SynField (attrs, _, id, fieldType, _, _, _, _, _)) ->
|
|> List.mapi (fun i fieldData ->
|
||||||
let id =
|
|
||||||
match id with
|
|
||||||
| None -> failwith "didn't get an ID on field"
|
|
||||||
| Some id -> id
|
|
||||||
|
|
||||||
let attrs = attrs |> List.collect (fun l -> l.Attributes)
|
|
||||||
|
|
||||||
let propertyNameAttr =
|
let propertyNameAttr =
|
||||||
attrs
|
fieldData.Attrs
|
||||||
|> List.tryFind (fun attr ->
|
|> List.tryFind (fun attr ->
|
||||||
attr.TypeName.AsString.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
(SynLongIdent.toString attr.TypeName)
|
||||||
|
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||||
)
|
)
|
||||||
|
|
||||||
let options =
|
let options = getParseOptions fieldData.Attrs
|
||||||
(JsonParseOption.None, attrs)
|
|
||||||
||> List.fold (fun options attr ->
|
|
||||||
if attr.TypeName.AsString.EndsWith ("JsonNumberHandling", StringComparison.Ordinal) then
|
|
||||||
let qualifiedEnumValue =
|
|
||||||
match SynExpr.stripOptionalParen attr.ArgExpr with
|
|
||||||
| SynExpr.LongIdent (_, SynLongIdent (ident, _, _), _, _) when
|
|
||||||
isJsonNumberHandling ident
|
|
||||||
->
|
|
||||||
// Make sure it's fully qualified
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.Create
|
|
||||||
[
|
|
||||||
"System"
|
|
||||||
"Text"
|
|
||||||
"Json"
|
|
||||||
"Serialization"
|
|
||||||
"JsonNumberHandling"
|
|
||||||
"AllowReadingFromString"
|
|
||||||
]
|
|
||||||
)
|
|
||||||
| _ -> attr.ArgExpr
|
|
||||||
|
|
||||||
{
|
|
||||||
JsonNumberHandlingArg = Some qualifiedEnumValue
|
|
||||||
}
|
|
||||||
else
|
|
||||||
options
|
|
||||||
)
|
|
||||||
|
|
||||||
let propertyName =
|
let propertyName =
|
||||||
match propertyNameAttr with
|
match propertyNameAttr with
|
||||||
| None ->
|
| None ->
|
||||||
let sb = StringBuilder id.idText.Length
|
let sb = StringBuilder fieldData.Ident.idText.Length
|
||||||
sb.Append (Char.ToLowerInvariant id.idText.[0]) |> ignore
|
|
||||||
|
|
||||||
if id.idText.Length > 1 then
|
sb.Append (Char.ToLowerInvariant fieldData.Ident.idText.[0])
|
||||||
sb.Append id.idText.[1..] |> ignore
|
|> ignore<StringBuilder>
|
||||||
|
|
||||||
sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst
|
if fieldData.Ident.idText.Length > 1 then
|
||||||
|
sb.Append (fieldData.Ident.idText.Substring 1) |> ignore<StringBuilder>
|
||||||
|
|
||||||
|
sb.ToString () |> SynExpr.CreateConst
|
||||||
| Some name -> name.ArgExpr
|
| Some name -> name.ArgExpr
|
||||||
|
|
||||||
let pattern =
|
createParseRhs options propertyName fieldData.Type
|
||||||
SynPat.LongIdent (
|
|> SynBinding.basic [ Ident.create $"arg_%i{i}" ] []
|
||||||
SynLongIdent.CreateFromLongIdent [ id ],
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
SynArgPats.Empty,
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
SynBinding.Let (
|
|
||||||
isInline = false,
|
|
||||||
isMutable = false,
|
|
||||||
expr = createParseRhs options propertyName fieldType,
|
|
||||||
valData = inputVal,
|
|
||||||
pattern = pattern
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let finalConstruction =
|
let finalConstruction =
|
||||||
fields
|
fields
|
||||||
|> List.map (fun (SynField (_, _, id, _, _, _, _, _, _)) ->
|
|> List.mapi (fun i fieldData ->
|
||||||
let id =
|
(SynLongIdent.createI fieldData.Ident, true), Some (SynExpr.createIdent $"arg_%i{i}")
|
||||||
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.instantiateRecord
|
|> AstHelper.instantiateRecord
|
||||||
|
|
||||||
let assignments =
|
(finalConstruction, assignments)
|
||||||
(finalConstruction, assignments)
|
||> List.fold (fun final assignment -> SynExpr.createLet [ assignment ] final)
|
||||||
||> List.fold (fun final assignment ->
|
|
||||||
SynExpr.LetOrUse (
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[ assignment ],
|
|
||||||
final,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
InKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
let pattern =
|
let createUnionMaker (spec : JsonParseOutputSpec) (typeName : LongIdent) (fields : UnionCase<Ident> list) =
|
||||||
SynPat.LongIdent (
|
fields
|
||||||
SynLongIdent.CreateFromLongIdent [ functionName ],
|
|> List.map (fun case ->
|
||||||
None,
|
let propertyName = JsonSerializeGenerator.getPropertyName case.Ident case.Attrs
|
||||||
None,
|
|
||||||
SynArgPats.Pats
|
|
||||||
[
|
|
||||||
SynPat.CreateTyped (
|
|
||||||
SynPat.CreateNamed inputArg,
|
|
||||||
SynType.LongIdent (
|
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|> SynPat.CreateParen
|
|
||||||
],
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
if spec.ExtensionMethods then
|
let body =
|
||||||
let binding =
|
if case.Fields.IsEmpty then
|
||||||
SynBinding.SynBinding (
|
SynExpr.createLongIdent' (typeName @ [ case.Ident ])
|
||||||
|
else
|
||||||
|
case.Fields
|
||||||
|
|> List.map (fun field ->
|
||||||
|
let propertyName = JsonSerializeGenerator.getPropertyName field.Ident field.Attrs
|
||||||
|
let options = getParseOptions field.Attrs
|
||||||
|
createParseRhs options propertyName field.Type
|
||||||
|
)
|
||||||
|
|> SynExpr.tuple
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ case.Ident ]))
|
||||||
|
|> SynExpr.createLet
|
||||||
|
[
|
||||||
|
SynExpr.index (SynExpr.CreateConst "data") (SynExpr.createIdent "node")
|
||||||
|
|> assertNotNull (SynExpr.CreateConst "data")
|
||||||
|
|> SynBinding.basic [ Ident.create "node" ] []
|
||||||
|
]
|
||||||
|
|
||||||
|
match propertyName with
|
||||||
|
| SynExpr.Const (synConst, _) ->
|
||||||
|
SynMatchClause.SynMatchClause (
|
||||||
|
SynPat.createConst synConst,
|
||||||
None,
|
None,
|
||||||
SynBindingKind.Normal,
|
body,
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[],
|
|
||||||
xmlDoc,
|
|
||||||
inputVal,
|
|
||||||
pattern,
|
|
||||||
Some returnInfo,
|
|
||||||
assignments,
|
|
||||||
range0,
|
range0,
|
||||||
DebugPointAtBinding.NoneAtInvisible,
|
DebugPointAtTarget.Yes,
|
||||||
{
|
{
|
||||||
LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0)
|
ArrowRange = Some range0
|
||||||
InlineKeyword = None
|
BarRange = Some range0
|
||||||
EqualsRange = Some range0
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
| _ ->
|
||||||
|
SynMatchClause.create (SynPat.named "x") body
|
||||||
|
|> SynMatchClause.withWhere (SynExpr.equals (SynExpr.createIdent "x") propertyName)
|
||||||
|
)
|
||||||
|
|> fun l ->
|
||||||
|
l
|
||||||
|
@ [
|
||||||
|
let fail =
|
||||||
|
SynExpr.plus (SynExpr.CreateConst "Unrecognised 'type' field value: ") (SynExpr.createIdent "v")
|
||||||
|
|> SynExpr.paren
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createIdent "failwith")
|
||||||
|
|
||||||
let mem = SynMemberDefn.Member (binding, range0)
|
SynMatchClause.SynMatchClause (
|
||||||
|
SynPat.named "v",
|
||||||
let containingType =
|
|
||||||
SynTypeDefn.SynTypeDefn (
|
|
||||||
SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"),
|
|
||||||
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0),
|
|
||||||
[ mem ],
|
|
||||||
None,
|
None,
|
||||||
|
fail,
|
||||||
range0,
|
range0,
|
||||||
|
DebugPointAtTarget.Yes,
|
||||||
{
|
{
|
||||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
ArrowRange = Some range0
|
||||||
EqualsRange = None
|
BarRange = Some range0
|
||||||
WithKeyword = None
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
]
|
||||||
|
|> SynExpr.createMatch (SynExpr.createIdent "ty")
|
||||||
|
|> SynExpr.createLet
|
||||||
|
[
|
||||||
|
let property = SynExpr.CreateConst "type"
|
||||||
|
|
||||||
SynModuleDecl.Types ([ containingType ], range0)
|
SynExpr.createIdent "node"
|
||||||
else
|
|> SynExpr.index property
|
||||||
let binding =
|
|> assertNotNull property
|
||||||
SynBinding.Let (
|
|> SynExpr.pipeThroughFunction (
|
||||||
isInline = false,
|
SynExpr.createLambda
|
||||||
isMutable = false,
|
"v"
|
||||||
xmldoc = xmlDoc,
|
(SynExpr.callGenericMethod "GetValue" [ Ident.create "string" ] (SynExpr.createIdent "v"))
|
||||||
returnInfo = returnInfo,
|
|
||||||
expr = assignments,
|
|
||||||
valData = inputVal,
|
|
||||||
pattern = pattern
|
|
||||||
)
|
)
|
||||||
|
|> SynBinding.basic [ Ident.create "ty" ] []
|
||||||
|
]
|
||||||
|
|
||||||
SynModuleDecl.CreateLet [ binding ]
|
let createModule (namespaceId : LongIdent) (spec : JsonParseOutputSpec) (typeDefn : SynTypeDefn) =
|
||||||
|
|
||||||
let createRecordModule (namespaceId : LongIdent) (spec : JsonParseOutputSpec) (typeDefn : SynTypeDefn) =
|
|
||||||
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||||
typeDefn
|
typeDefn
|
||||||
|
|
||||||
let (SynComponentInfo (_attributes, _typeParams, _constraints, recordId, _, _preferPostfix, _access, _)) =
|
let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, access, _)) =
|
||||||
synComponentInfo
|
synComponentInfo
|
||||||
|
|
||||||
match synTypeDefnRepr with
|
let attributes =
|
||||||
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, recordFields, _recordRange), _) ->
|
if spec.ExtensionMethods then
|
||||||
|
[ SynAttribute.autoOpen ]
|
||||||
|
else
|
||||||
|
[ SynAttribute.requireQualifiedAccess ; SynAttribute.compilationRepresentation ]
|
||||||
|
|
||||||
let decls = [ createMaker spec recordId recordFields ]
|
let xmlDoc =
|
||||||
|
let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "."
|
||||||
|
|
||||||
let attributes =
|
let description =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
"extension members"
|
||||||
else
|
else
|
||||||
[
|
"methods"
|
||||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
|
||||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
|
||||||
]
|
|
||||||
|
|
||||||
let xmlDoc =
|
$"Module containing JSON parsing %s{description} for the %s{fullyQualified} type"
|
||||||
let fullyQualified = recordId |> Seq.map (fun i -> i.idText) |> String.concat "."
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let description =
|
let moduleName =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
"extension members"
|
match ident with
|
||||||
else
|
| [] -> failwith "unexpectedly got an empty identifier for record name"
|
||||||
"methods"
|
| ident ->
|
||||||
|
let expanded =
|
||||||
|
List.last ident
|
||||||
|
|> fun i -> i.idText
|
||||||
|
|> fun s -> s + "JsonParseExtension"
|
||||||
|
|> Ident.create
|
||||||
|
|
||||||
$" Module containing JSON parsing %s{description} for the %s{fullyQualified} type"
|
List.take (List.length ident - 1) ident @ [ expanded ]
|
||||||
|> PreXmlDoc.Create
|
else
|
||||||
|
ident
|
||||||
|
|
||||||
let moduleName =
|
let info =
|
||||||
if spec.ExtensionMethods then
|
SynComponentInfo.createLong moduleName
|
||||||
match recordId with
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
| [] -> failwith "unexpectedly got an empty identifier for record name"
|
|> SynComponentInfo.setAccessibility access
|
||||||
| recordId ->
|
|> SynComponentInfo.addAttributes attributes
|
||||||
let expanded =
|
|
||||||
List.last recordId
|
|
||||||
|> fun i -> i.idText
|
|
||||||
|> fun s -> s + "JsonParseExtension"
|
|
||||||
|> Ident.Create
|
|
||||||
|
|
||||||
List.take (List.length recordId - 1) recordId @ [ expanded ]
|
let decl =
|
||||||
else
|
match synTypeDefnRepr with
|
||||||
recordId
|
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, fields, _range), _) ->
|
||||||
|
fields |> List.map SynField.extractWithIdent |> createRecordMaker spec
|
||||||
|
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (_accessibility, cases, _range), _) ->
|
||||||
|
let optionGet (i : Ident option) =
|
||||||
|
match i with
|
||||||
|
| None -> failwith "WoofWare.Myriad requires union cases to have identifiers on each field."
|
||||||
|
| Some i -> i
|
||||||
|
|
||||||
let info =
|
cases
|
||||||
SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc)
|
|> List.map SynUnionCase.extract
|
||||||
|
|> List.map (UnionCase.mapIdentFields optionGet)
|
||||||
|
|> createUnionMaker spec ident
|
||||||
|
| _ -> failwithf "Not a record or union type"
|
||||||
|
|
||||||
let mdl = SynModuleDecl.CreateNestedModule (info, decls)
|
[ scaffolding spec ident decl ]
|
||||||
|
|> SynModuleDecl.nestedModule info
|
||||||
|
|> List.singleton
|
||||||
|
|> SynModuleOrNamespace.createNamespace namespaceId
|
||||||
|
|
||||||
SynModuleOrNamespace.CreateNamespace (namespaceId, decls = [ mdl ])
|
open Myriad.Core
|
||||||
| _ -> failwithf "Not a record type"
|
|
||||||
|
|
||||||
/// Myriad generator that provides a method (possibly an extension method) for a record type,
|
/// Myriad generator that provides a method (possibly an extension method) for a record type,
|
||||||
/// containing a JSON parse function.
|
/// containing a JSON parse function.
|
||||||
@@ -617,10 +555,20 @@ type JsonParseGenerator () =
|
|||||||
let ast, _ =
|
let ast, _ =
|
||||||
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
|
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
|
||||||
|
|
||||||
let records = Ast.extractRecords ast
|
let recordsAndUnions =
|
||||||
|
Ast.extractTypeDefn ast
|
||||||
|
|> List.map (fun (name, defns) ->
|
||||||
|
defns
|
||||||
|
|> List.choose (fun defn ->
|
||||||
|
if Ast.isRecord defn then Some defn
|
||||||
|
elif Ast.isDu defn then Some defn
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|> fun defns -> name, defns
|
||||||
|
)
|
||||||
|
|
||||||
let namespaceAndRecords =
|
let namespaceAndTypes =
|
||||||
records
|
recordsAndUnions
|
||||||
|> List.choose (fun (ns, types) ->
|
|> List.choose (fun (ns, types) ->
|
||||||
types
|
types
|
||||||
|> List.choose (fun typeDef ->
|
|> List.choose (fun typeDef ->
|
||||||
@@ -648,13 +596,9 @@ type JsonParseGenerator () =
|
|||||||
)
|
)
|
||||||
|
|
||||||
let modules =
|
let modules =
|
||||||
namespaceAndRecords
|
namespaceAndTypes
|
||||||
|> List.collect (fun (ns, records) ->
|
|> List.collect (fun (ns, types) ->
|
||||||
records
|
types |> List.map (fun (ty, spec) -> JsonParseGenerator.createModule ns spec ty)
|
||||||
|> List.map (fun (record, spec) ->
|
|
||||||
let recordModule = JsonParseGenerator.createRecordModule ns spec record
|
|
||||||
recordModule
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Output.Ast modules
|
Output.Ast modules
|
||||||
|
@@ -3,9 +3,6 @@ namespace WoofWare.Myriad.Plugins
|
|||||||
open System
|
open System
|
||||||
open System.Text
|
open System.Text
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Fantomas.FCS.Xml
|
|
||||||
open Myriad.Core
|
|
||||||
|
|
||||||
type internal JsonSerializeOutputSpec =
|
type internal JsonSerializeOutputSpec =
|
||||||
{
|
{
|
||||||
@@ -15,7 +12,6 @@ type internal JsonSerializeOutputSpec =
|
|||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal JsonSerializeGenerator =
|
module internal JsonSerializeGenerator =
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
open Myriad.Core.Ast
|
|
||||||
|
|
||||||
/// Given `input.Ident`, for example, choose how to add it to the ambient `node`.
|
/// Given `input.Ident`, for example, choose how to add it to the ambient `node`.
|
||||||
/// The result is a line like `(fun ident -> InnerType.toJsonNode ident)` or `(fun ident -> JsonValue.Create ident)`.
|
/// The result is a line like `(fun ident -> InnerType.toJsonNode ident)` or `(fun ident -> JsonValue.Create ident)`.
|
||||||
@@ -30,9 +26,7 @@ module internal JsonSerializeGenerator =
|
|||||||
| Uri ->
|
| Uri ->
|
||||||
// JsonValue.Create<type>
|
// JsonValue.Create<type>
|
||||||
SynExpr.TypeApp (
|
SynExpr.TypeApp (
|
||||||
SynExpr.CreateLongIdent (
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ],
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ]
|
|
||||||
),
|
|
||||||
range0,
|
range0,
|
||||||
[ fieldType ],
|
[ fieldType ],
|
||||||
[],
|
[],
|
||||||
@@ -42,39 +36,24 @@ module internal JsonSerializeGenerator =
|
|||||||
)
|
)
|
||||||
| OptionType ty ->
|
| OptionType ty ->
|
||||||
// fun field -> match field with | None -> JsonValue.Create null | Some v -> {serializeNode ty} field
|
// fun field -> match field with | None -> JsonValue.Create null | Some v -> {serializeNode ty} field
|
||||||
SynExpr.CreateMatch (
|
let noneClause =
|
||||||
SynExpr.CreateIdentString "field",
|
// The absolutely galaxy-brained implementation of JsonValue has `JsonValue.Parse "null"`
|
||||||
[
|
// identically equal to null. We have to work around this later, but we might as well just
|
||||||
SynMatchClause.Create (
|
// be efficient here and whip up the null directly.
|
||||||
SynPat.CreateLongIdent (SynLongIdent.CreateString "None", []),
|
SynExpr.createNull ()
|
||||||
None,
|
|> SynExpr.upcast' (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||||
// The absolutely galaxy-brained implementation of JsonValue has `JsonValue.Parse "null"`
|
|> SynMatchClause.create (SynPat.named "None")
|
||||||
// identically equal to null. We have to work around this later, but we might as well just
|
|
||||||
// be efficient here and whip up the null directly.
|
|
||||||
SynExpr.CreateNull
|
|
||||||
|> SynExpr.upcast' (
|
|
||||||
SynType.CreateLongIdent (
|
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
SynMatchClause.Create (
|
let someClause =
|
||||||
SynPat.CreateLongIdent (
|
SynExpr.applyFunction (serializeNode ty) (SynExpr.createIdent "field")
|
||||||
SynLongIdent.CreateString "Some",
|
|> SynExpr.paren
|
||||||
[ SynPat.CreateNamed (Ident.Create "field") ]
|
|> SynExpr.upcast' (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
||||||
),
|
|> SynMatchClause.create (
|
||||||
None,
|
SynPat.identWithArgs [ Ident.create "Some" ] (SynArgPats.create [ Ident.create "field" ])
|
||||||
SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "field")
|
)
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|> SynExpr.upcast' (
|
[ noneClause ; someClause ]
|
||||||
SynType.CreateLongIdent (
|
|> SynExpr.createMatch (SynExpr.createIdent "field")
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|> SynExpr.createLambda "field"
|
|> SynExpr.createLambda "field"
|
||||||
| ArrayType ty
|
| ArrayType ty
|
||||||
| ListType ty ->
|
| ListType ty ->
|
||||||
@@ -82,116 +61,69 @@ module internal JsonSerializeGenerator =
|
|||||||
// let arr = JsonArray ()
|
// let arr = JsonArray ()
|
||||||
// for mem in field do arr.Add ({serializeNode} mem)
|
// for mem in field do arr.Add ({serializeNode} mem)
|
||||||
// arr
|
// arr
|
||||||
SynExpr.LetOrUse (
|
[
|
||||||
false,
|
SynExpr.ForEach (
|
||||||
false,
|
DebugPointAtFor.Yes range0,
|
||||||
|
DebugPointAtInOrTo.Yes range0,
|
||||||
|
SeqExprOnly.SeqExprOnly false,
|
||||||
|
true,
|
||||||
|
SynPat.named "mem",
|
||||||
|
SynExpr.createIdent "field",
|
||||||
|
SynExpr.applyFunction
|
||||||
|
(SynExpr.createLongIdent [ "arr" ; "Add" ])
|
||||||
|
(SynExpr.paren (SynExpr.applyFunction (serializeNode ty) (SynExpr.createIdent "mem"))),
|
||||||
|
range0
|
||||||
|
)
|
||||||
|
SynExpr.createIdent "arr"
|
||||||
|
]
|
||||||
|
|> SynExpr.sequential
|
||||||
|
|> SynExpr.createLet
|
||||||
[
|
[
|
||||||
SynBinding.Let (
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonArray" ]
|
||||||
pattern = SynPat.CreateNamed (Ident.Create "arr"),
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
expr =
|
|> SynBinding.basic [ Ident.create "arr" ] []
|
||||||
SynExpr.CreateApp (
|
]
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonArray" ]
|
|
||||||
),
|
|
||||||
SynExpr.CreateConst SynConst.Unit
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
SynExpr.CreateSequential
|
|
||||||
[
|
|
||||||
SynExpr.ForEach (
|
|
||||||
DebugPointAtFor.Yes range0,
|
|
||||||
DebugPointAtInOrTo.Yes range0,
|
|
||||||
SeqExprOnly.SeqExprOnly false,
|
|
||||||
true,
|
|
||||||
SynPat.CreateNamed (Ident.Create "mem"),
|
|
||||||
SynExpr.CreateIdent (Ident.Create "field"),
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "arr" ; "Add" ]),
|
|
||||||
SynExpr.CreateParen (
|
|
||||||
SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "mem")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
SynExpr.CreateIdentString "arr"
|
|
||||||
],
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
InKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|> SynExpr.createLambda "field"
|
|> SynExpr.createLambda "field"
|
||||||
| IDictionaryType (keyType, valueType)
|
| IDictionaryType (_keyType, valueType)
|
||||||
| DictionaryType (keyType, valueType)
|
| DictionaryType (_keyType, valueType)
|
||||||
| IReadOnlyDictionaryType (keyType, valueType)
|
| IReadOnlyDictionaryType (_keyType, valueType)
|
||||||
| MapType (keyType, valueType) ->
|
| MapType (_keyType, valueType) ->
|
||||||
// fun field ->
|
// fun field ->
|
||||||
// let ret = JsonObject ()
|
// let ret = JsonObject ()
|
||||||
// for (KeyValue(key, value)) in field do
|
// for (KeyValue(key, value)) in field do
|
||||||
// ret.Add (key.ToString (), {serializeNode} value)
|
// ret.Add (key.ToString (), {serializeNode} value)
|
||||||
// ret
|
// ret
|
||||||
SynExpr.LetOrUse (
|
[
|
||||||
false,
|
SynExpr.ForEach (
|
||||||
false,
|
DebugPointAtFor.Yes range0,
|
||||||
|
DebugPointAtInOrTo.Yes range0,
|
||||||
|
SeqExprOnly.SeqExprOnly false,
|
||||||
|
true,
|
||||||
|
SynPat.paren (
|
||||||
|
SynPat.identWithArgs
|
||||||
|
[ Ident.create "KeyValue" ]
|
||||||
|
(SynArgPats.create [ Ident.create "key" ; Ident.create "value" ])
|
||||||
|
),
|
||||||
|
SynExpr.createIdent "field",
|
||||||
|
SynExpr.applyFunction
|
||||||
|
(SynExpr.createLongIdent [ "ret" ; "Add" ])
|
||||||
|
(SynExpr.tuple
|
||||||
|
[
|
||||||
|
SynExpr.createLongIdent [ "key" ; "ToString" ]
|
||||||
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
|
SynExpr.applyFunction (serializeNode valueType) (SynExpr.createIdent "value")
|
||||||
|
]),
|
||||||
|
range0
|
||||||
|
)
|
||||||
|
SynExpr.createIdent "ret"
|
||||||
|
]
|
||||||
|
|> SynExpr.sequential
|
||||||
|
|> SynExpr.createLet
|
||||||
[
|
[
|
||||||
SynBinding.Let (
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||||
pattern = SynPat.CreateNamed (Ident.Create "ret"),
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
expr =
|
|> SynBinding.basic [ Ident.create "ret" ] []
|
||||||
SynExpr.CreateApp (
|
]
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
|
||||||
),
|
|
||||||
SynExpr.CreateConst SynConst.Unit
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
SynExpr.CreateSequential
|
|
||||||
[
|
|
||||||
SynExpr.ForEach (
|
|
||||||
DebugPointAtFor.Yes range0,
|
|
||||||
DebugPointAtInOrTo.Yes range0,
|
|
||||||
SeqExprOnly.SeqExprOnly false,
|
|
||||||
true,
|
|
||||||
SynPat.CreateParen (
|
|
||||||
SynPat.CreateLongIdent (
|
|
||||||
SynLongIdent.CreateString "KeyValue",
|
|
||||||
[
|
|
||||||
SynPat.CreateParen (
|
|
||||||
SynPat.Tuple (
|
|
||||||
false,
|
|
||||||
[
|
|
||||||
SynPat.CreateNamed (Ident.Create "key")
|
|
||||||
SynPat.CreateNamed (Ident.Create "value")
|
|
||||||
],
|
|
||||||
[ range0 ],
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
SynExpr.CreateIdent (Ident.Create "field"),
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "ret" ; "Add" ]),
|
|
||||||
SynExpr.CreateParenedTuple
|
|
||||||
[
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "key" ; "ToString" ]),
|
|
||||||
SynExpr.CreateConst SynConst.Unit
|
|
||||||
)
|
|
||||||
SynExpr.CreateApp (serializeNode valueType, SynExpr.CreateIdentString "value")
|
|
||||||
]
|
|
||||||
),
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
SynExpr.CreateIdentString "ret"
|
|
||||||
],
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
InKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|> SynExpr.createLambda "field"
|
|> SynExpr.createLambda "field"
|
||||||
| _ ->
|
| _ ->
|
||||||
// {type}.toJsonNode
|
// {type}.toJsonNode
|
||||||
@@ -200,213 +132,189 @@ module internal JsonSerializeGenerator =
|
|||||||
| SynType.LongIdent ident -> ident.LongIdent
|
| SynType.LongIdent ident -> ident.LongIdent
|
||||||
| _ -> failwith $"Unrecognised type: %+A{fieldType}"
|
| _ -> failwith $"Unrecognised type: %+A{fieldType}"
|
||||||
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (typeName @ [ Ident.Create "toJsonNode" ]))
|
SynExpr.createLongIdent' (typeName @ [ Ident.create "toJsonNode" ])
|
||||||
|
|
||||||
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
/// propertyName is probably a string literal, but it could be a [<Literal>] variable
|
||||||
/// `node.Add ({propertyName}, {toJsonNode})`
|
/// `node.Add ({propertyName}, {toJsonNode})`
|
||||||
let createSerializeRhs (propertyName : SynExpr) (fieldId : Ident) (fieldType : SynType) : SynExpr =
|
let createSerializeRhsRecord (propertyName : SynExpr) (fieldId : Ident) (fieldType : SynType) : SynExpr =
|
||||||
let func = SynExpr.CreateLongIdent (SynLongIdent.Create [ "node" ; "Add" ])
|
[
|
||||||
|
propertyName
|
||||||
|
SynExpr.applyFunction
|
||||||
|
(serializeNode fieldType)
|
||||||
|
(SynExpr.createLongIdent' [ Ident.create "input" ; fieldId ])
|
||||||
|
]
|
||||||
|
|> SynExpr.tuple
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||||
|
|
||||||
let args =
|
let getPropertyName (fieldId : Ident) (attrs : SynAttribute list) : SynExpr =
|
||||||
SynExpr.CreateParenedTuple
|
let propertyNameAttr =
|
||||||
[
|
attrs
|
||||||
propertyName
|
|> List.tryFind (fun attr ->
|
||||||
SynExpr.CreateApp (
|
(SynLongIdent.toString attr.TypeName)
|
||||||
serializeNode fieldType,
|
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ Ident.Create "input" ; fieldId ])
|
)
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
SynExpr.CreateApp (func, args)
|
match propertyNameAttr with
|
||||||
|
| None ->
|
||||||
|
let sb = StringBuilder fieldId.idText.Length
|
||||||
|
sb.Append (Char.ToLowerInvariant fieldId.idText.[0]) |> ignore
|
||||||
|
|
||||||
let createMaker (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (fields : SynField list) =
|
if fieldId.idText.Length > 1 then
|
||||||
let xmlDoc = PreXmlDoc.Create " Serialize to a JSON node"
|
sb.Append fieldId.idText.[1..] |> ignore
|
||||||
|
|
||||||
|
sb.ToString () |> SynExpr.CreateConst
|
||||||
|
| Some name -> name.ArgExpr
|
||||||
|
|
||||||
|
/// `populateNode` will be inserted before we return the `node` variable.
|
||||||
|
///
|
||||||
|
/// That is, we give you access to a `JsonObject` called `node`,
|
||||||
|
/// and you have access to a variable `inputArgName` which is of type `typeName`.
|
||||||
|
/// Your job is to provide a `populateNode` expression which has the side effect
|
||||||
|
/// of mutating `node` to faithfully reflect the value of `inputArgName`.
|
||||||
|
let scaffolding
|
||||||
|
(spec : JsonSerializeOutputSpec)
|
||||||
|
(typeName : LongIdent)
|
||||||
|
(inputArgName : Ident)
|
||||||
|
(populateNode : SynExpr)
|
||||||
|
: SynModuleDecl
|
||||||
|
=
|
||||||
|
let xmlDoc = PreXmlDoc.create "Serialize to a JSON node"
|
||||||
|
|
||||||
let returnInfo =
|
let returnInfo =
|
||||||
SynBindingReturnInfo.Create (
|
SynLongIdent.createS' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
|
||||||
SynType.LongIdent (SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ])
|
|> SynType.LongIdent
|
||||||
)
|
|
||||||
|
|
||||||
let inputArg = Ident.Create "input"
|
let functionName = Ident.create "toJsonNode"
|
||||||
let functionName = Ident.Create "toJsonNode"
|
|
||||||
|
|
||||||
let inputVal =
|
|
||||||
let memberFlags =
|
|
||||||
if spec.ExtensionMethods then
|
|
||||||
{
|
|
||||||
SynMemberFlags.IsInstance = false
|
|
||||||
SynMemberFlags.IsDispatchSlot = false
|
|
||||||
SynMemberFlags.IsOverrideOrExplicitImpl = false
|
|
||||||
SynMemberFlags.IsFinal = false
|
|
||||||
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
|
||||||
SynMemberFlags.MemberKind = SynMemberKind.Member
|
|
||||||
}
|
|
||||||
|> Some
|
|
||||||
else
|
|
||||||
None
|
|
||||||
|
|
||||||
let thisIdOpt = if spec.ExtensionMethods then None else Some inputArg
|
|
||||||
|
|
||||||
SynValData.SynValData (
|
|
||||||
memberFlags,
|
|
||||||
SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty),
|
|
||||||
thisIdOpt
|
|
||||||
)
|
|
||||||
|
|
||||||
let assignments =
|
let assignments =
|
||||||
fields
|
[
|
||||||
|> List.map (fun (SynField (attrs, _, id, fieldType, _, _, _, _, _)) ->
|
populateNode
|
||||||
let id =
|
SynExpr.Upcast (SynExpr.createIdent "node", SynType.Anon range0, range0)
|
||||||
match id with
|
]
|
||||||
| None -> failwith "didn't get an ID on field"
|
|> SynExpr.sequential
|
||||||
| Some id -> id
|
|> SynExpr.createLet
|
||||||
|
|
||||||
let attrs = attrs |> List.collect (fun l -> l.Attributes)
|
|
||||||
|
|
||||||
let propertyNameAttr =
|
|
||||||
attrs
|
|
||||||
|> 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
|
|
||||||
)
|
|
||||||
|
|
||||||
createSerializeRhs propertyName id fieldType
|
|
||||||
)
|
|
||||||
|
|
||||||
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.instantiateRecord
|
|
||||||
|
|
||||||
let assignments = assignments |> SynExpr.CreateSequential
|
|
||||||
|
|
||||||
let assignments =
|
|
||||||
SynExpr.LetOrUse (
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[
|
[
|
||||||
SynBinding.Let (
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||||
pattern = SynPat.CreateNamed (Ident.Create "node"),
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
expr =
|
|> SynBinding.basic [ Ident.create "node" ] []
|
||||||
SynExpr.CreateApp (
|
]
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
|
||||||
),
|
|
||||||
SynExpr.CreateConst SynConst.Unit
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
SynExpr.CreateSequential
|
|
||||||
[
|
|
||||||
SynExpr.Do (assignments, range0)
|
|
||||||
SynExpr.Upcast (SynExpr.CreateIdentString "node", SynType.Anon range0, range0)
|
|
||||||
],
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
InKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
let pattern =
|
let pattern =
|
||||||
SynPat.LongIdent (
|
SynPat.namedI inputArgName
|
||||||
SynLongIdent.CreateFromLongIdent [ functionName ],
|
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create typeName))
|
||||||
None,
|
|
||||||
None,
|
|
||||||
SynArgPats.Pats
|
|
||||||
[
|
|
||||||
SynPat.CreateTyped (
|
|
||||||
SynPat.CreateNamed inputArg,
|
|
||||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName)
|
|
||||||
)
|
|
||||||
|> SynPat.CreateParen
|
|
||||||
],
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
let binding =
|
let componentInfo =
|
||||||
SynBinding.SynBinding (
|
SynComponentInfo.createLong typeName
|
||||||
None,
|
|> SynComponentInfo.withDocString (PreXmlDoc.create "Extension methods for JSON parsing")
|
||||||
SynBindingKind.Normal,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[],
|
|
||||||
xmlDoc,
|
|
||||||
inputVal,
|
|
||||||
pattern,
|
|
||||||
Some returnInfo,
|
|
||||||
assignments,
|
|
||||||
range0,
|
|
||||||
DebugPointAtBinding.NoneAtInvisible,
|
|
||||||
{
|
|
||||||
LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0)
|
|
||||||
InlineKeyword = None
|
|
||||||
EqualsRange = Some range0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
let mem = SynMemberDefn.Member (binding, range0)
|
let memberDef =
|
||||||
|
assignments
|
||||||
|
|> SynBinding.basic [ functionName ] [ pattern ]
|
||||||
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
|
|> SynMemberDefn.staticMember
|
||||||
|
|
||||||
let containingType =
|
let containingType =
|
||||||
SynTypeDefn.SynTypeDefn (
|
SynTypeDefnRepr.augmentation ()
|
||||||
SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"),
|
|> SynTypeDefn.create componentInfo
|
||||||
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0),
|
|> SynTypeDefn.withMemberDefns [ memberDef ]
|
||||||
[ mem ],
|
|
||||||
None,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
|
||||||
EqualsRange = None
|
|
||||||
WithKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
SynModuleDecl.Types ([ containingType ], range0)
|
SynModuleDecl.Types ([ containingType ], range0)
|
||||||
else
|
else
|
||||||
let binding =
|
assignments
|
||||||
SynBinding.Let (
|
|> SynBinding.basic [ functionName ] [ pattern ]
|
||||||
isInline = false,
|
|> SynBinding.withReturnAnnotation returnInfo
|
||||||
isMutable = false,
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
xmldoc = xmlDoc,
|
|> SynModuleDecl.createLet
|
||||||
returnInfo = returnInfo,
|
|
||||||
expr = assignments,
|
let recordModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (fields : SynField list) =
|
||||||
valData = inputVal,
|
let inputArg = Ident.create "input"
|
||||||
pattern = pattern
|
let fields = fields |> List.map SynField.extractWithIdent
|
||||||
|
|
||||||
|
fields
|
||||||
|
|> List.map (fun fieldData ->
|
||||||
|
let propertyName = getPropertyName fieldData.Ident fieldData.Attrs
|
||||||
|
createSerializeRhsRecord propertyName fieldData.Ident fieldData.Type
|
||||||
|
)
|
||||||
|
|> SynExpr.sequential
|
||||||
|
|> fun expr -> SynExpr.Do (expr, range0)
|
||||||
|
|> scaffolding spec typeName inputArg
|
||||||
|
|
||||||
|
let unionModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (cases : SynUnionCase list) =
|
||||||
|
let inputArg = Ident.create "input"
|
||||||
|
let fields = cases |> List.map SynUnionCase.extract
|
||||||
|
|
||||||
|
fields
|
||||||
|
|> List.map (fun unionCase ->
|
||||||
|
let propertyName = getPropertyName unionCase.Ident unionCase.Attrs
|
||||||
|
|
||||||
|
let caseNames = unionCase.Fields |> List.mapi (fun i _ -> Ident.create $"arg%i{i}")
|
||||||
|
|
||||||
|
let argPats = SynArgPats.create caseNames
|
||||||
|
|
||||||
|
let pattern =
|
||||||
|
SynPat.LongIdent (
|
||||||
|
SynLongIdent.create (typeName @ [ unionCase.Ident ]),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
argPats,
|
||||||
|
None,
|
||||||
|
range0
|
||||||
)
|
)
|
||||||
|
|
||||||
SynModuleDecl.CreateLet [ binding ]
|
let typeLine =
|
||||||
|
[
|
||||||
|
SynExpr.CreateConst "type"
|
||||||
|
SynExpr.applyFunction
|
||||||
|
(SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ])
|
||||||
|
propertyName
|
||||||
|
]
|
||||||
|
|> SynExpr.tuple
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||||
|
|
||||||
let createRecordModule
|
let dataNode =
|
||||||
|
SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
|
||||||
|
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||||
|
|> SynBinding.basic [ Ident.create "dataNode" ] []
|
||||||
|
|
||||||
|
let dataBindings =
|
||||||
|
(unionCase.Fields, caseNames)
|
||||||
|
||> List.zip
|
||||||
|
|> List.map (fun (fieldData, caseName) ->
|
||||||
|
let propertyName = getPropertyName (Option.get fieldData.Ident) fieldData.Attrs
|
||||||
|
|
||||||
|
let node =
|
||||||
|
SynExpr.applyFunction (serializeNode fieldData.Type) (SynExpr.createIdent' caseName)
|
||||||
|
|
||||||
|
[ propertyName ; node ]
|
||||||
|
|> SynExpr.tuple
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "dataNode" ; "Add" ])
|
||||||
|
)
|
||||||
|
|
||||||
|
let assignToNode =
|
||||||
|
[ SynExpr.CreateConst "data" ; SynExpr.createIdent "dataNode" ]
|
||||||
|
|> SynExpr.tuple
|
||||||
|
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ])
|
||||||
|
|
||||||
|
let dataNode =
|
||||||
|
SynExpr.sequential (dataBindings @ [ assignToNode ])
|
||||||
|
|> SynExpr.createLet [ dataNode ]
|
||||||
|
|
||||||
|
let action =
|
||||||
|
[
|
||||||
|
yield typeLine
|
||||||
|
if not dataBindings.IsEmpty then
|
||||||
|
yield dataNode
|
||||||
|
]
|
||||||
|
|> SynExpr.sequential
|
||||||
|
|
||||||
|
SynMatchClause.create pattern action
|
||||||
|
)
|
||||||
|
|> SynExpr.createMatch (SynExpr.createIdent' inputArg)
|
||||||
|
|> scaffolding spec typeName inputArg
|
||||||
|
|
||||||
|
let createModule
|
||||||
(namespaceId : LongIdent)
|
(namespaceId : LongIdent)
|
||||||
(opens : SynOpenDeclTarget list)
|
(opens : SynOpenDeclTarget list)
|
||||||
(spec : JsonSerializeOutputSpec)
|
(spec : JsonSerializeOutputSpec)
|
||||||
@@ -415,60 +323,63 @@ module internal JsonSerializeGenerator =
|
|||||||
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||||
typeDefn
|
typeDefn
|
||||||
|
|
||||||
let (SynComponentInfo (_attributes, _typeParams, _constraints, recordId, _, _preferPostfix, _access, _)) =
|
let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, access, _)) =
|
||||||
synComponentInfo
|
synComponentInfo
|
||||||
|
|
||||||
match synTypeDefnRepr with
|
let attributes =
|
||||||
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, recordFields, _recordRange), _) ->
|
if spec.ExtensionMethods then
|
||||||
|
[ SynAttribute.autoOpen ]
|
||||||
|
else
|
||||||
|
[ SynAttribute.requireQualifiedAccess ; SynAttribute.compilationRepresentation ]
|
||||||
|
|
||||||
let decls = [ createMaker spec recordId recordFields ]
|
let xmlDoc =
|
||||||
|
let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "."
|
||||||
|
|
||||||
let attributes =
|
let description =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
[ SynAttributeList.Create SynAttribute.autoOpen ]
|
"extension members"
|
||||||
else
|
else
|
||||||
[
|
"methods"
|
||||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
|
||||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
|
||||||
]
|
|
||||||
|
|
||||||
let xmlDoc =
|
$"Module containing JSON serializing %s{description} for the %s{fullyQualified} type"
|
||||||
let fullyQualified = recordId |> Seq.map (fun i -> i.idText) |> String.concat "."
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let description =
|
let moduleName =
|
||||||
if spec.ExtensionMethods then
|
if spec.ExtensionMethods then
|
||||||
"extension members"
|
match ident with
|
||||||
else
|
| [] -> failwith "unexpectedly got an empty identifier for type name"
|
||||||
"methods"
|
| ident ->
|
||||||
|
let expanded =
|
||||||
|
List.last ident
|
||||||
|
|> fun i -> i.idText
|
||||||
|
|> fun s -> s + "JsonSerializeExtension"
|
||||||
|
|> Ident.create
|
||||||
|
|
||||||
$" Module containing JSON serializing %s{description} for the %s{fullyQualified} type"
|
List.take (List.length ident - 1) ident @ [ expanded ]
|
||||||
|> PreXmlDoc.Create
|
else
|
||||||
|
ident
|
||||||
|
|
||||||
let moduleName =
|
let info =
|
||||||
if spec.ExtensionMethods then
|
SynComponentInfo.createLong moduleName
|
||||||
match recordId with
|
|> SynComponentInfo.addAttributes attributes
|
||||||
| [] -> failwith "unexpectedly got an empty identifier for record name"
|
|> SynComponentInfo.setAccessibility access
|
||||||
| recordId ->
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
let expanded =
|
|
||||||
List.last recordId
|
|
||||||
|> fun i -> i.idText
|
|
||||||
|> fun s -> s + "JsonSerializeExtension"
|
|
||||||
|> Ident.Create
|
|
||||||
|
|
||||||
List.take (List.length recordId - 1) recordId @ [ expanded ]
|
let decls =
|
||||||
else
|
match synTypeDefnRepr with
|
||||||
recordId
|
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, recordFields, _range), _) ->
|
||||||
|
[ recordModule spec ident recordFields ]
|
||||||
|
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (_accessibility, unionFields, _range), _) ->
|
||||||
|
[ unionModule spec ident unionFields ]
|
||||||
|
| _ -> failwithf "Only record types currently supported."
|
||||||
|
|
||||||
let info =
|
[
|
||||||
SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc)
|
yield! opens |> List.map SynModuleDecl.openAny
|
||||||
|
yield SynModuleDecl.nestedModule info decls
|
||||||
|
]
|
||||||
|
|> SynModuleOrNamespace.createNamespace namespaceId
|
||||||
|
|
||||||
let mdl = SynModuleDecl.CreateNestedModule (info, decls)
|
open Myriad.Core
|
||||||
|
|
||||||
SynModuleOrNamespace.CreateNamespace (
|
|
||||||
namespaceId,
|
|
||||||
decls = (opens |> List.map SynModuleDecl.CreateOpen) @ [ mdl ]
|
|
||||||
)
|
|
||||||
| _ -> failwithf "Not a record type"
|
|
||||||
|
|
||||||
/// Myriad generator that provides a method (possibly an extension method) for a record type,
|
/// Myriad generator that provides a method (possibly an extension method) for a record type,
|
||||||
/// containing a JSON serialization function.
|
/// containing a JSON serialization function.
|
||||||
@@ -482,10 +393,20 @@ type JsonSerializeGenerator () =
|
|||||||
let ast, _ =
|
let ast, _ =
|
||||||
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
|
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
|
||||||
|
|
||||||
let records = Ast.extractRecords ast
|
let recordsAndUnions =
|
||||||
|
Ast.extractTypeDefn ast
|
||||||
|
|> List.map (fun (name, defns) ->
|
||||||
|
defns
|
||||||
|
|> List.choose (fun defn ->
|
||||||
|
if Ast.isRecord defn then Some defn
|
||||||
|
elif Ast.isDu defn then Some defn
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|> fun defns -> name, defns
|
||||||
|
)
|
||||||
|
|
||||||
let namespaceAndRecords =
|
let namespaceAndTypes =
|
||||||
records
|
recordsAndUnions
|
||||||
|> List.choose (fun (ns, types) ->
|
|> List.choose (fun (ns, types) ->
|
||||||
types
|
types
|
||||||
|> List.choose (fun typeDef ->
|
|> List.choose (fun typeDef ->
|
||||||
@@ -515,13 +436,10 @@ type JsonSerializeGenerator () =
|
|||||||
let opens = AstHelper.extractOpens ast
|
let opens = AstHelper.extractOpens ast
|
||||||
|
|
||||||
let modules =
|
let modules =
|
||||||
namespaceAndRecords
|
namespaceAndTypes
|
||||||
|> List.collect (fun (ns, records) ->
|
|> List.collect (fun (ns, types) ->
|
||||||
records
|
types
|
||||||
|> List.map (fun (record, spec) ->
|
|> List.map (fun (ty, spec) -> JsonSerializeGenerator.createModule ns opens spec ty)
|
||||||
let recordModule = JsonSerializeGenerator.createRecordModule ns opens spec record
|
|
||||||
recordModule
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Output.Ast modules
|
Output.Ast modules
|
||||||
|
30
WoofWare.Myriad.Plugins/Primitives.fs
Normal file
30
WoofWare.Myriad.Plugins/Primitives.fs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal Primitives =
|
||||||
|
/// Given e.g. "byte", returns "System.Byte".
|
||||||
|
let qualifyType (typeName : string) : LongIdent option =
|
||||||
|
match typeName with
|
||||||
|
| "float32"
|
||||||
|
| "single" -> [ "System" ; "Single" ] |> Some
|
||||||
|
| "float"
|
||||||
|
| "double" -> [ "System" ; "Double" ] |> Some
|
||||||
|
| "byte"
|
||||||
|
| "uint8" -> [ "System" ; "Byte" ] |> Some
|
||||||
|
| "sbyte"
|
||||||
|
| "int8" -> [ "System" ; "SByte" ] |> Some
|
||||||
|
| "int16" -> [ "System" ; "Int16" ] |> Some
|
||||||
|
| "int"
|
||||||
|
| "int32" -> [ "System" ; "Int32" ] |> Some
|
||||||
|
| "int64" -> [ "System" ; "Int64" ] |> Some
|
||||||
|
| "uint16" -> [ "System" ; "UInt16" ] |> Some
|
||||||
|
| "uint"
|
||||||
|
| "uint32" -> [ "System" ; "UInt32" ] |> Some
|
||||||
|
| "uint64" -> [ "System" ; "UInt64" ] |> Some
|
||||||
|
| "char" -> [ "System" ; "Char" ] |> Some
|
||||||
|
| "decimal" -> [ "System" ; "Decimal" ] |> Some
|
||||||
|
| _ -> None
|
||||||
|
|> Option.map (List.map (fun i -> (Ident (i, range0))))
|
@@ -1,14 +1,11 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Fantomas.FCS.Xml
|
open Fantomas.FCS.Xml
|
||||||
open Myriad.Core
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal RemoveOptionsGenerator =
|
module internal RemoveOptionsGenerator =
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
open Myriad.Core.Ast
|
|
||||||
|
|
||||||
let private removeOption (s : SynField) : SynField =
|
let private removeOption (s : SynField) : SynField =
|
||||||
let (SynField.SynField (synAttributeLists,
|
let (SynField.SynField (synAttributeLists,
|
||||||
@@ -47,7 +44,7 @@ module internal RemoveOptionsGenerator =
|
|||||||
(fields : SynField list)
|
(fields : SynField list)
|
||||||
=
|
=
|
||||||
let fields : SynField list = fields |> List.map removeOption
|
let fields : SynField list = fields |> List.map removeOption
|
||||||
let name = Ident.Create "Short"
|
let name = Ident.create "Short"
|
||||||
|
|
||||||
let record =
|
let record =
|
||||||
{
|
{
|
||||||
@@ -63,94 +60,51 @@ module internal RemoveOptionsGenerator =
|
|||||||
|
|
||||||
SynModuleDecl.Types ([ typeDecl ], range0)
|
SynModuleDecl.Types ([ typeDecl ], range0)
|
||||||
|
|
||||||
let createMaker (withOptionsType : LongIdent) (withoutOptionsType : LongIdent) (fields : SynField list) =
|
let createMaker (withOptionsType : LongIdent) (withoutOptionsType : LongIdent) (fields : SynFieldData<Ident> list) =
|
||||||
let xmlDoc = PreXmlDoc.Create " Remove the optional members of the input."
|
let xmlDoc = PreXmlDoc.create "Remove the optional members of the input."
|
||||||
|
|
||||||
let returnInfo =
|
let inputArg = Ident.create "input"
|
||||||
SynBindingReturnInfo.Create (SynType.LongIdent (SynLongIdent.CreateFromLongIdent withOptionsType))
|
let functionName = Ident.create "shorten"
|
||||||
|
|
||||||
let inputArg = Ident.Create "input"
|
|
||||||
let functionName = Ident.Create "shorten"
|
|
||||||
|
|
||||||
let inputVal =
|
|
||||||
SynValData.SynValData (
|
|
||||||
None,
|
|
||||||
SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty),
|
|
||||||
Some inputArg
|
|
||||||
)
|
|
||||||
|
|
||||||
let body =
|
let body =
|
||||||
fields
|
fields
|
||||||
|> List.map (fun (SynField (_, _, id, fieldType, _, _, _, _, _)) ->
|
|> List.map (fun fieldData ->
|
||||||
let id =
|
|
||||||
match id with
|
|
||||||
| None -> failwith "Expected record field to have an identifying name"
|
|
||||||
| Some id -> id
|
|
||||||
|
|
||||||
let accessor =
|
let accessor =
|
||||||
SynExpr.LongIdent (false, SynLongIdent ([ inputArg ; id ], [ range0 ], []), None, range0)
|
SynExpr.LongIdent (
|
||||||
|
false,
|
||||||
|
SynLongIdent ([ inputArg ; fieldData.Ident ], [ range0 ], []),
|
||||||
|
None,
|
||||||
|
range0
|
||||||
|
)
|
||||||
|
|
||||||
let body =
|
let body =
|
||||||
match fieldType with
|
match fieldData.Type with
|
||||||
| OptionType _ ->
|
| OptionType _ ->
|
||||||
SynExpr.CreateApp (
|
accessor
|
||||||
SynExpr.CreateAppInfix (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.LongIdent (
|
SynExpr.applyFunction
|
||||||
false,
|
(SynExpr.createLongIdent [ "Option" ; "defaultWith" ])
|
||||||
SynLongIdent.SynLongIdent (
|
(SynExpr.createLongIdent' (
|
||||||
[ Ident.Create "op_PipeRight" ],
|
withoutOptionsType
|
||||||
[],
|
@ [ Ident.create (sprintf "Default%s" fieldData.Ident.idText) ]
|
||||||
[ Some (IdentTrivia.OriginalNotation "|>") ]
|
))
|
||||||
),
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
),
|
|
||||||
accessor
|
|
||||||
),
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "Option.defaultWith"),
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.CreateFromLongIdent (
|
|
||||||
withoutOptionsType @ [ Ident.Create (sprintf "Default%s" id.idText) ]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
| _ -> accessor
|
| _ -> accessor
|
||||||
|
|
||||||
(SynLongIdent.CreateFromLongIdent [ id ], true), Some body
|
(SynLongIdent.createI fieldData.Ident, true), Some body
|
||||||
)
|
)
|
||||||
|> AstHelper.instantiateRecord
|
|> AstHelper.instantiateRecord
|
||||||
|
|
||||||
let pattern =
|
SynBinding.basic
|
||||||
SynPat.LongIdent (
|
[ functionName ]
|
||||||
SynLongIdent.CreateFromLongIdent [ functionName ],
|
[
|
||||||
None,
|
SynPat.named inputArg.idText
|
||||||
None,
|
|> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create withoutOptionsType))
|
||||||
SynArgPats.Pats
|
]
|
||||||
[
|
body
|
||||||
SynPat.CreateTyped (
|
|> SynBinding.withXmlDoc xmlDoc
|
||||||
SynPat.CreateNamed inputArg,
|
|> SynBinding.withReturnAnnotation (SynType.LongIdent (SynLongIdent.create withOptionsType))
|
||||||
SynType.LongIdent (SynLongIdent.CreateFromLongIdent withoutOptionsType)
|
|> SynModuleDecl.createLet
|
||||||
)
|
|
||||||
|> SynPat.CreateParen
|
|
||||||
],
|
|
||||||
None,
|
|
||||||
range0
|
|
||||||
)
|
|
||||||
|
|
||||||
let binding =
|
|
||||||
SynBinding.Let (
|
|
||||||
isInline = false,
|
|
||||||
isMutable = false,
|
|
||||||
xmldoc = xmlDoc,
|
|
||||||
returnInfo = returnInfo,
|
|
||||||
expr = body,
|
|
||||||
valData = inputVal,
|
|
||||||
pattern = pattern
|
|
||||||
)
|
|
||||||
|
|
||||||
SynModuleDecl.CreateLet [ binding ]
|
|
||||||
|
|
||||||
let createRecordModule (namespaceId : LongIdent) (typeDefn : SynTypeDefn) =
|
let createRecordModule (namespaceId : LongIdent) (typeDefn : SynTypeDefn) =
|
||||||
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) =
|
||||||
@@ -160,35 +114,35 @@ module internal RemoveOptionsGenerator =
|
|||||||
synComponentInfo
|
synComponentInfo
|
||||||
|
|
||||||
match synTypeDefnRepr with
|
match synTypeDefnRepr with
|
||||||
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (accessibility, recordFields, _recordRange), _) ->
|
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (accessibility, fields, _range), _) ->
|
||||||
|
let fieldData = fields |> List.map SynField.extractWithIdent
|
||||||
|
|
||||||
let decls =
|
let decls =
|
||||||
[
|
[
|
||||||
createType (Some doc) accessibility typeParams recordFields
|
createType (Some doc) accessibility typeParams fields
|
||||||
createMaker [ Ident.Create "Short" ] recordId recordFields
|
createMaker [ Ident.create "Short" ] recordId fieldData
|
||||||
]
|
|
||||||
|
|
||||||
let attributes =
|
|
||||||
[
|
|
||||||
SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ())
|
|
||||||
SynAttributeList.Create SynAttribute.compilationRepresentation
|
|
||||||
]
|
]
|
||||||
|
|
||||||
let xmlDoc =
|
let xmlDoc =
|
||||||
recordId
|
recordId
|
||||||
|> Seq.map (fun i -> i.idText)
|
|> Seq.map (fun i -> i.idText)
|
||||||
|> String.concat "."
|
|> String.concat "."
|
||||||
|> sprintf " Module containing an option-truncated version of the %s type"
|
|> sprintf "Module containing an option-truncated version of the %s type"
|
||||||
|> PreXmlDoc.Create
|
|> PreXmlDoc.create
|
||||||
|
|
||||||
let info =
|
let info =
|
||||||
SynComponentInfo.Create (recordId, attributes = attributes, xmldoc = xmlDoc)
|
SynComponentInfo.createLong recordId
|
||||||
|
|> SynComponentInfo.withDocString xmlDoc
|
||||||
|
|> SynComponentInfo.addAttributes [ SynAttribute.compilationRepresentation ]
|
||||||
|
|> SynComponentInfo.addAttributes [ SynAttribute.requireQualifiedAccess ]
|
||||||
|
|
||||||
let mdl = SynModuleDecl.CreateNestedModule (info, decls)
|
SynModuleDecl.nestedModule info decls
|
||||||
|
|> List.singleton
|
||||||
SynModuleOrNamespace.CreateNamespace (namespaceId, decls = [ mdl ])
|
|> SynModuleOrNamespace.createNamespace namespaceId
|
||||||
| _ -> failwithf "Not a record type"
|
| _ -> failwithf "Not a record type"
|
||||||
|
|
||||||
|
open Myriad.Core
|
||||||
|
|
||||||
/// Myriad generator that stamps out a record with option types stripped
|
/// Myriad generator that stamps out a record with option types stripped
|
||||||
/// from the fields at the top level.
|
/// from the fields at the top level.
|
||||||
[<MyriadGenerator("remove-options")>]
|
[<MyriadGenerator("remove-options")>]
|
||||||
|
@@ -1,31 +0,0 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
|
||||||
open Fantomas.FCS.Text.Range
|
|
||||||
open Myriad.Core
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module internal SynAttribute =
|
|
||||||
let internal compilationRepresentation : SynAttribute =
|
|
||||||
{
|
|
||||||
TypeName = SynLongIdent.CreateString "CompilationRepresentation"
|
|
||||||
ArgExpr =
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
false,
|
|
||||||
SynLongIdent.Create [ "CompilationRepresentationFlags" ; "ModuleSuffix" ],
|
|
||||||
None
|
|
||||||
)
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
Target = None
|
|
||||||
AppliesToGetterAndSetter = false
|
|
||||||
Range = range0
|
|
||||||
}
|
|
||||||
|
|
||||||
let internal autoOpen : SynAttribute =
|
|
||||||
{
|
|
||||||
TypeName = SynLongIdent.CreateString "AutoOpen"
|
|
||||||
ArgExpr = SynExpr.CreateConst SynConst.Unit
|
|
||||||
Target = None
|
|
||||||
AppliesToGetterAndSetter = false
|
|
||||||
Range = range0
|
|
||||||
}
|
|
@@ -1,313 +0,0 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
|
||||||
open Fantomas.FCS.SyntaxTrivia
|
|
||||||
open Myriad.Core
|
|
||||||
open Myriad.Core.Ast
|
|
||||||
open Fantomas.FCS.Text.Range
|
|
||||||
|
|
||||||
type internal CompExprBinding =
|
|
||||||
| LetBang of varName : string * rhs : SynExpr
|
|
||||||
| Let of varName : string * rhs : SynExpr
|
|
||||||
| Use of varName : string * rhs : SynExpr
|
|
||||||
| Do of body : SynExpr
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module internal SynExpr =
|
|
||||||
|
|
||||||
/// {expr} |> {func}
|
|
||||||
let pipeThroughFunction (func : SynExpr) (expr : SynExpr) : SynExpr =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateAppInfix (
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_PipeRight" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "|>") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
expr
|
|
||||||
),
|
|
||||||
func
|
|
||||||
)
|
|
||||||
|
|
||||||
/// if {cond} then {trueBranch} else {falseBranch}
|
|
||||||
/// Note that this function puts the trueBranch last, for pipelining convenience:
|
|
||||||
/// we assume that the `else` branch is more like an error case and is less interesting.
|
|
||||||
let ifThenElse (cond : SynExpr) (falseBranch : SynExpr) (trueBranch : SynExpr) : SynExpr =
|
|
||||||
SynExpr.IfThenElse (
|
|
||||||
cond,
|
|
||||||
trueBranch,
|
|
||||||
Some falseBranch,
|
|
||||||
DebugPointAtBinding.Yes range0,
|
|
||||||
false,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
IfKeyword = range0
|
|
||||||
IsElif = false
|
|
||||||
ThenKeyword = range0
|
|
||||||
ElseKeyword = Some range0
|
|
||||||
IfToThenRange = range0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
/// try {body} with | {exc} as exc -> {handler}
|
|
||||||
let pipeThroughTryWith (exc : SynPat) (handler : SynExpr) (body : SynExpr) : SynExpr =
|
|
||||||
let clause =
|
|
||||||
SynMatchClause.Create (SynPat.As (exc, SynPat.CreateNamed (Ident.Create "exc"), range0), None, handler)
|
|
||||||
|
|
||||||
SynExpr.TryWith (
|
|
||||||
body,
|
|
||||||
[ clause ],
|
|
||||||
range0,
|
|
||||||
DebugPointAtTry.Yes range0,
|
|
||||||
DebugPointAtWith.Yes range0,
|
|
||||||
{
|
|
||||||
TryKeyword = range0
|
|
||||||
TryToWithRange = range0
|
|
||||||
WithKeyword = range0
|
|
||||||
WithToEndRange = range0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {a} = {b}
|
|
||||||
let equals (a : SynExpr) (b : SynExpr) =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateAppInfix (
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
Ident.CreateLong "op_Equality",
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "=") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
a
|
|
||||||
),
|
|
||||||
b
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {a} + {b}
|
|
||||||
let plus (a : SynExpr) (b : SynExpr) =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateAppInfix (
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
Ident.CreateLong "op_Addition",
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "+") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
a
|
|
||||||
),
|
|
||||||
b
|
|
||||||
)
|
|
||||||
|
|
||||||
let rec stripOptionalParen (expr : SynExpr) : SynExpr =
|
|
||||||
match expr with
|
|
||||||
| SynExpr.Paren (expr, _, _, _) -> stripOptionalParen expr
|
|
||||||
| expr -> expr
|
|
||||||
|
|
||||||
/// Given e.g. "byte", returns "System.Byte".
|
|
||||||
let qualifyPrimitiveType (typeName : string) : LongIdent =
|
|
||||||
match typeName with
|
|
||||||
| "float32" -> [ "System" ; "Single" ]
|
|
||||||
| "float" -> [ "System" ; "Double" ]
|
|
||||||
| "byte"
|
|
||||||
| "uint8" -> [ "System" ; "Byte" ]
|
|
||||||
| "sbyte" -> [ "System" ; "SByte" ]
|
|
||||||
| "int16" -> [ "System" ; "Int16" ]
|
|
||||||
| "int" -> [ "System" ; "Int32" ]
|
|
||||||
| "int64" -> [ "System" ; "Int64" ]
|
|
||||||
| "uint16" -> [ "System" ; "UInt16" ]
|
|
||||||
| "uint"
|
|
||||||
| "uint32" -> [ "System" ; "UInt32" ]
|
|
||||||
| "uint64" -> [ "System" ; "UInt64" ]
|
|
||||||
| _ -> failwith $"Unable to identify a parsing function `string -> %s{typeName}`"
|
|
||||||
|> List.map Ident.Create
|
|
||||||
|
|
||||||
/// {obj}.{meth} {arg}
|
|
||||||
let callMethodArg (meth : string) (arg : SynExpr) (obj : SynExpr) : SynExpr =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.DotGet (
|
|
||||||
obj,
|
|
||||||
range0,
|
|
||||||
SynLongIdent.SynLongIdent (id = [ Ident.Create meth ], dotRanges = [], trivia = [ None ]),
|
|
||||||
range0
|
|
||||||
),
|
|
||||||
arg
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {obj}.{meth}()
|
|
||||||
let callMethod (meth : string) (obj : SynExpr) : SynExpr =
|
|
||||||
callMethodArg meth (SynExpr.CreateConst SynConst.Unit) obj
|
|
||||||
|
|
||||||
/// {obj}.{meth}<ty>()
|
|
||||||
let callGenericMethod (meth : string) (ty : string) (obj : SynExpr) : SynExpr =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.TypeApp (
|
|
||||||
SynExpr.DotGet (obj, range0, SynLongIdent.Create [ meth ], range0),
|
|
||||||
range0,
|
|
||||||
[ SynType.CreateLongIdent ty ],
|
|
||||||
[],
|
|
||||||
Some range0,
|
|
||||||
range0,
|
|
||||||
range0
|
|
||||||
),
|
|
||||||
SynExpr.CreateConst SynConst.Unit
|
|
||||||
)
|
|
||||||
|
|
||||||
let index (property : SynExpr) (obj : SynExpr) : SynExpr =
|
|
||||||
SynExpr.DotIndexedGet (obj, property, range0, range0)
|
|
||||||
|
|
||||||
/// (fun {varName} -> {body})
|
|
||||||
let createLambda (varName : string) (body : SynExpr) : SynExpr =
|
|
||||||
let parsedDataPat = [ SynPat.CreateNamed (Ident.Create varName) ]
|
|
||||||
|
|
||||||
SynExpr.Lambda (
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
SynSimplePats.Create [ SynSimplePat.CreateId (Ident.Create varName) ],
|
|
||||||
body,
|
|
||||||
Some (parsedDataPat, body),
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
ArrowRange = Some range0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|> SynExpr.CreateParen
|
|
||||||
|
|
||||||
let reraise : SynExpr =
|
|
||||||
SynExpr.CreateApp (SynExpr.CreateIdent (Ident.Create "reraise"), SynExpr.CreateConst SynConst.Unit)
|
|
||||||
|
|
||||||
/// {body} |> fun a -> Async.StartAsTask (a, ?cancellationToken=ct)
|
|
||||||
let startAsTask (ct : SynLongIdent) (body : SynExpr) =
|
|
||||||
let lambda =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "StartAsTask" ]),
|
|
||||||
SynExpr.CreateParenedTuple
|
|
||||||
[
|
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.CreateString "a")
|
|
||||||
equals
|
|
||||||
(SynExpr.LongIdent (true, SynLongIdent.CreateString "cancellationToken", None, range0))
|
|
||||||
(SynExpr.CreateLongIdent ct)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|> createLambda "a"
|
|
||||||
|
|
||||||
pipeThroughFunction lambda body
|
|
||||||
|
|
||||||
/// {compExpr} { {lets} ; return {ret} }
|
|
||||||
let createCompExpr (compExpr : string) (retBody : SynExpr) (lets : CompExprBinding list) : SynExpr =
|
|
||||||
let retStatement = SynExpr.YieldOrReturn ((false, true), retBody, range0)
|
|
||||||
|
|
||||||
let contents : SynExpr =
|
|
||||||
(retStatement, List.rev lets)
|
|
||||||
||> List.fold (fun state binding ->
|
|
||||||
match binding with
|
|
||||||
| LetBang (lhs, rhs) ->
|
|
||||||
SynExpr.LetOrUseBang (
|
|
||||||
DebugPointAtBinding.Yes range0,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
SynPat.CreateNamed (Ident.Create lhs),
|
|
||||||
rhs,
|
|
||||||
[],
|
|
||||||
state,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
EqualsRange = Some range0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
| Let (lhs, rhs) ->
|
|
||||||
SynExpr.LetOrUse (
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
[ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ],
|
|
||||||
state,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
SynExprLetOrUseTrivia.InKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
| Use (lhs, rhs) ->
|
|
||||||
SynExpr.LetOrUse (
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
[ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ],
|
|
||||||
state,
|
|
||||||
range0,
|
|
||||||
{
|
|
||||||
SynExprLetOrUseTrivia.InKeyword = None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
| Do body -> SynExpr.CreateSequential [ SynExpr.Do (body, range0) ; state ]
|
|
||||||
)
|
|
||||||
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateIdent (Ident.Create compExpr),
|
|
||||||
SynExpr.ComputationExpr (false, contents, range0)
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {expr} |> Async.AwaitTask
|
|
||||||
let awaitTask (expr : SynExpr) : SynExpr =
|
|
||||||
expr
|
|
||||||
|> pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "AwaitTask" ]))
|
|
||||||
|
|
||||||
/// {ident}.ToString ()
|
|
||||||
/// with special casing for some types like DateTime
|
|
||||||
let toString (ty : SynType) (ident : SynExpr) =
|
|
||||||
match ty with
|
|
||||||
| DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-dd")
|
|
||||||
| DateTime ->
|
|
||||||
ident
|
|
||||||
|> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-ddTHH:mm:ss")
|
|
||||||
| _ -> callMethod "ToString" ident
|
|
||||||
|
|
||||||
let upcast' (ty : SynType) (e : SynExpr) = SynExpr.Upcast (e, ty, range0)
|
|
||||||
|
|
||||||
let synBindingTriviaZero (isMember : bool) =
|
|
||||||
{
|
|
||||||
SynBindingTrivia.EqualsRange = Some range0
|
|
||||||
InlineKeyword = None
|
|
||||||
LeadingKeyword =
|
|
||||||
if isMember then
|
|
||||||
SynLeadingKeyword.Member range0
|
|
||||||
else
|
|
||||||
SynLeadingKeyword.Let range0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// {ident} - {rhs}
|
|
||||||
let minus (ident : SynLongIdent) (rhs : SynExpr) : SynExpr =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateAppInfix (
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_Subtraction" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation "-") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
SynExpr.CreateLongIdent ident
|
|
||||||
),
|
|
||||||
rhs
|
|
||||||
)
|
|
||||||
|
|
||||||
/// {ident} - {n}
|
|
||||||
let minusN (ident : SynLongIdent) (n : int) : SynExpr =
|
|
||||||
minus ident (SynExpr.CreateConst (SynConst.Int32 n))
|
|
||||||
|
|
||||||
/// {y} > {x}
|
|
||||||
let greaterThan (x : SynExpr) (y : SynExpr) : SynExpr =
|
|
||||||
SynExpr.CreateApp (
|
|
||||||
SynExpr.CreateAppInfix (
|
|
||||||
SynExpr.CreateLongIdent (
|
|
||||||
SynLongIdent.SynLongIdent (
|
|
||||||
[ Ident.Create "op_GreaterThan" ],
|
|
||||||
[],
|
|
||||||
[ Some (IdentTrivia.OriginalNotation ">") ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
y
|
|
||||||
),
|
|
||||||
x
|
|
||||||
)
|
|
49
WoofWare.Myriad.Plugins/SynExpr/CompExpr.fs
Normal file
49
WoofWare.Myriad.Plugins/SynExpr/CompExpr.fs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
|
||||||
|
type internal CompExprBinding =
|
||||||
|
| LetBang of varName : string * rhs : SynExpr
|
||||||
|
| Let of varName : string * rhs : SynExpr
|
||||||
|
| Use of varName : string * rhs : SynExpr
|
||||||
|
| Do of body : SynExpr
|
||||||
|
|
||||||
|
(*
|
||||||
|
Potential API!
|
||||||
|
type internal CompExprBindings =
|
||||||
|
private
|
||||||
|
{
|
||||||
|
/// These are stored in reverse.
|
||||||
|
Bindings : CompExprBinding list
|
||||||
|
CompExprName : string
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal CompExprBindings =
|
||||||
|
let make (name : string) : CompExprBindings =
|
||||||
|
{
|
||||||
|
Bindings = []
|
||||||
|
CompExprName = name
|
||||||
|
}
|
||||||
|
|
||||||
|
let thenDo (body : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (Do body :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
let thenLet (varName : string) (value : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (Let (varName, value) :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
let thenLetBang (varName : string) (value : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (LetBang (varName, value) :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let thenUse (varName : string) (value : SynExpr) (bindings : CompExprBindings) =
|
||||||
|
{ bindings with
|
||||||
|
Bindings = (LetBang (varName, value) :: bindings.Bindings)
|
||||||
|
}
|
||||||
|
*)
|
@@ -3,12 +3,14 @@ namespace WoofWare.Myriad.Plugins
|
|||||||
open System
|
open System
|
||||||
open System.Text
|
open System.Text
|
||||||
open Fantomas.FCS.Syntax
|
open Fantomas.FCS.Syntax
|
||||||
open Myriad.Core
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal Ident =
|
module internal Ident =
|
||||||
|
let inline create (s : string) = Ident (s, range0)
|
||||||
|
|
||||||
let lowerFirstLetter (x : Ident) : Ident =
|
let lowerFirstLetter (x : Ident) : Ident =
|
||||||
let result = StringBuilder x.idText.Length
|
let result = StringBuilder x.idText.Length
|
||||||
result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore
|
result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore
|
||||||
result.Append x.idText.[1..] |> ignore
|
result.Append x.idText.[1..] |> ignore
|
||||||
Ident.Create ((result : StringBuilder).ToString ())
|
create ((result : StringBuilder).ToString ())
|
9
WoofWare.Myriad.Plugins/SynExpr/PreXmlDoc.fs
Normal file
9
WoofWare.Myriad.Plugins/SynExpr/PreXmlDoc.fs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal PreXmlDoc =
|
||||||
|
let create (s : string) : PreXmlDoc =
|
||||||
|
PreXmlDoc.Create ([| " " + s |], range0)
|
16
WoofWare.Myriad.Plugins/SynExpr/SynArgPats.fs
Normal file
16
WoofWare.Myriad.Plugins/SynExpr/SynArgPats.fs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynArgPats =
|
||||||
|
let create (caseNames : Ident list) : SynArgPats =
|
||||||
|
match caseNames.Length with
|
||||||
|
| 0 -> SynArgPats.Pats []
|
||||||
|
| 1 -> [ SynPat.named caseNames.[0].idText ] |> SynArgPats.Pats
|
||||||
|
| _ ->
|
||||||
|
caseNames
|
||||||
|
|> List.map (fun i -> SynPat.named i.idText)
|
||||||
|
|> SynPat.tuple
|
||||||
|
|> List.singleton
|
||||||
|
|> SynArgPats.Pats
|
36
WoofWare.Myriad.Plugins/SynExpr/SynAttribute.fs
Normal file
36
WoofWare.Myriad.Plugins/SynExpr/SynAttribute.fs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynAttribute =
|
||||||
|
let internal compilationRepresentation : SynAttribute =
|
||||||
|
{
|
||||||
|
TypeName = SynLongIdent.createS "CompilationRepresentation"
|
||||||
|
ArgExpr =
|
||||||
|
[ "CompilationRepresentationFlags" ; "ModuleSuffix" ]
|
||||||
|
|> SynExpr.createLongIdent
|
||||||
|
|> SynExpr.paren
|
||||||
|
Target = None
|
||||||
|
AppliesToGetterAndSetter = false
|
||||||
|
Range = range0
|
||||||
|
}
|
||||||
|
|
||||||
|
let internal requireQualifiedAccess : SynAttribute =
|
||||||
|
{
|
||||||
|
TypeName = SynLongIdent.createS "RequireQualifiedAccess"
|
||||||
|
ArgExpr = SynExpr.CreateConst ()
|
||||||
|
Target = None
|
||||||
|
AppliesToGetterAndSetter = false
|
||||||
|
Range = range0
|
||||||
|
}
|
||||||
|
|
||||||
|
let internal autoOpen : SynAttribute =
|
||||||
|
{
|
||||||
|
TypeName = SynLongIdent.createS "AutoOpen"
|
||||||
|
ArgExpr = SynExpr.CreateConst ()
|
||||||
|
Target = None
|
||||||
|
AppliesToGetterAndSetter = false
|
||||||
|
Range = range0
|
||||||
|
}
|
204
WoofWare.Myriad.Plugins/SynExpr/SynBinding.fs
Normal file
204
WoofWare.Myriad.Plugins/SynExpr/SynBinding.fs
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynBinding =
|
||||||
|
|
||||||
|
let rec private stripParen (pat : SynPat) =
|
||||||
|
match pat with
|
||||||
|
| SynPat.Paren (p, _) -> stripParen p
|
||||||
|
| _ -> pat
|
||||||
|
|
||||||
|
let rec private getName (pat : SynPat) : Ident option =
|
||||||
|
match stripParen pat with
|
||||||
|
| SynPat.Named (SynIdent.SynIdent (name, _), _, _, _) -> Some name
|
||||||
|
| SynPat.Typed (pat, _, _) -> getName pat
|
||||||
|
| SynPat.LongIdent (SynLongIdent.SynLongIdent (longIdent, _, _), _, _, _, _, _) ->
|
||||||
|
match longIdent with
|
||||||
|
| [ x ] -> Some x
|
||||||
|
| _ -> failwithf "got long ident %O ; can only get the name of a long ident with one component" longIdent
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let private getArgInfo (pat : SynPat) : SynArgInfo list =
|
||||||
|
// TODO: this only copes with one layer of tupling
|
||||||
|
match stripParen pat with
|
||||||
|
| SynPat.Tuple (_, pats, _, _) -> pats |> List.map (fun pat -> SynArgInfo.SynArgInfo ([], false, getName pat))
|
||||||
|
| pat -> [ SynArgInfo.SynArgInfo (SynAttributes.Empty, false, getName pat) ]
|
||||||
|
|
||||||
|
let triviaZero (isMember : bool) =
|
||||||
|
{
|
||||||
|
SynBindingTrivia.EqualsRange = Some range0
|
||||||
|
InlineKeyword = None
|
||||||
|
LeadingKeyword =
|
||||||
|
if isMember then
|
||||||
|
SynLeadingKeyword.Member range0
|
||||||
|
else
|
||||||
|
SynLeadingKeyword.Let range0
|
||||||
|
}
|
||||||
|
|
||||||
|
let basic (name : LongIdent) (args : SynPat list) (body : SynExpr) : SynBinding =
|
||||||
|
let valInfo : SynValInfo =
|
||||||
|
args
|
||||||
|
|> List.map getArgInfo
|
||||||
|
|> fun x -> SynValInfo.SynValInfo (x, SynArgInfo.SynArgInfo ([], false, None))
|
||||||
|
|
||||||
|
SynBinding.SynBinding (
|
||||||
|
None,
|
||||||
|
SynBindingKind.Normal,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
[],
|
||||||
|
PreXmlDoc.Empty,
|
||||||
|
SynValData.SynValData (None, valInfo, None),
|
||||||
|
SynPat.identWithArgs name (SynArgPats.Pats args),
|
||||||
|
None,
|
||||||
|
body,
|
||||||
|
range0,
|
||||||
|
DebugPointAtBinding.Yes range0,
|
||||||
|
triviaZero false
|
||||||
|
)
|
||||||
|
|
||||||
|
let withAccessibility (acc : SynAccess option) (binding : SynBinding) : SynBinding =
|
||||||
|
match binding with
|
||||||
|
| SynBinding (_, kind, inl, mut, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia) ->
|
||||||
|
let headPat =
|
||||||
|
match headPat with
|
||||||
|
| SynPat.LongIdent (ident, extra, options, argPats, _, range) ->
|
||||||
|
SynPat.LongIdent (ident, extra, options, argPats, acc, range)
|
||||||
|
| _ -> failwithf "unrecognised head pattern: %O" headPat
|
||||||
|
|
||||||
|
SynBinding (acc, kind, inl, mut, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia)
|
||||||
|
|
||||||
|
let withXmlDoc (doc : PreXmlDoc) (binding : SynBinding) : SynBinding =
|
||||||
|
match binding with
|
||||||
|
| SynBinding (acc, kind, inl, mut, attrs, _, valData, headPat, returnInfo, expr, range, debugPoint, trivia) ->
|
||||||
|
SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, returnInfo, expr, range, debugPoint, trivia)
|
||||||
|
|
||||||
|
let withReturnAnnotation (ty : SynType) (binding : SynBinding) : SynBinding =
|
||||||
|
match binding with
|
||||||
|
| SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, _, expr, range, debugPoint, trivia) ->
|
||||||
|
let retInfo =
|
||||||
|
SynBindingReturnInfo.SynBindingReturnInfo (
|
||||||
|
ty,
|
||||||
|
range0,
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
ColonRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
SynBinding (
|
||||||
|
acc,
|
||||||
|
kind,
|
||||||
|
inl,
|
||||||
|
mut,
|
||||||
|
attrs,
|
||||||
|
doc,
|
||||||
|
valData,
|
||||||
|
headPat,
|
||||||
|
Some retInfo,
|
||||||
|
expr,
|
||||||
|
range,
|
||||||
|
debugPoint,
|
||||||
|
trivia
|
||||||
|
)
|
||||||
|
|
||||||
|
let inline makeInline (binding : SynBinding) : SynBinding =
|
||||||
|
match binding with
|
||||||
|
| SynBinding (acc, kind, _, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) ->
|
||||||
|
SynBinding (
|
||||||
|
acc,
|
||||||
|
kind,
|
||||||
|
true,
|
||||||
|
mut,
|
||||||
|
attrs,
|
||||||
|
doc,
|
||||||
|
valData,
|
||||||
|
headPat,
|
||||||
|
ret,
|
||||||
|
expr,
|
||||||
|
range,
|
||||||
|
debugPoint,
|
||||||
|
{ trivia with
|
||||||
|
InlineKeyword = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let inline makeNotInline (binding : SynBinding) : SynBinding =
|
||||||
|
match binding with
|
||||||
|
| SynBinding (acc, kind, _, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) ->
|
||||||
|
SynBinding (
|
||||||
|
acc,
|
||||||
|
kind,
|
||||||
|
false,
|
||||||
|
mut,
|
||||||
|
attrs,
|
||||||
|
doc,
|
||||||
|
valData,
|
||||||
|
headPat,
|
||||||
|
ret,
|
||||||
|
expr,
|
||||||
|
range,
|
||||||
|
debugPoint,
|
||||||
|
{ trivia with
|
||||||
|
InlineKeyword = None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let inline setInline (isInline : bool) (binding : SynBinding) : SynBinding =
|
||||||
|
if isInline then
|
||||||
|
makeInline binding
|
||||||
|
else
|
||||||
|
makeNotInline binding
|
||||||
|
|
||||||
|
let makeStaticMember (binding : SynBinding) : SynBinding =
|
||||||
|
let memberFlags =
|
||||||
|
{
|
||||||
|
SynMemberFlags.IsInstance = false
|
||||||
|
SynMemberFlags.IsDispatchSlot = false
|
||||||
|
SynMemberFlags.IsOverrideOrExplicitImpl = false
|
||||||
|
SynMemberFlags.IsFinal = false
|
||||||
|
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
||||||
|
SynMemberFlags.MemberKind = SynMemberKind.Member
|
||||||
|
}
|
||||||
|
|
||||||
|
match binding with
|
||||||
|
| SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) ->
|
||||||
|
let valData =
|
||||||
|
match valData with
|
||||||
|
| SynValData.SynValData (_, valInfo, _) -> SynValData.SynValData (Some memberFlags, valInfo, None)
|
||||||
|
|
||||||
|
let trivia =
|
||||||
|
{ trivia with
|
||||||
|
LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0)
|
||||||
|
}
|
||||||
|
|
||||||
|
SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia)
|
||||||
|
|
||||||
|
let makeInstanceMember (binding : SynBinding) : SynBinding =
|
||||||
|
let memberFlags =
|
||||||
|
{
|
||||||
|
SynMemberFlags.IsInstance = true
|
||||||
|
SynMemberFlags.IsDispatchSlot = false
|
||||||
|
SynMemberFlags.IsOverrideOrExplicitImpl = true
|
||||||
|
SynMemberFlags.IsFinal = false
|
||||||
|
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
||||||
|
SynMemberFlags.MemberKind = SynMemberKind.Member
|
||||||
|
}
|
||||||
|
|
||||||
|
match binding with
|
||||||
|
| SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) ->
|
||||||
|
let valData =
|
||||||
|
match valData with
|
||||||
|
| SynValData.SynValData (_, valInfo, _) -> SynValData.SynValData (Some memberFlags, valInfo, None)
|
||||||
|
|
||||||
|
let trivia =
|
||||||
|
{ trivia with
|
||||||
|
LeadingKeyword = SynLeadingKeyword.Member range0
|
||||||
|
}
|
||||||
|
|
||||||
|
SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia)
|
50
WoofWare.Myriad.Plugins/SynExpr/SynComponentInfo.fs
Normal file
50
WoofWare.Myriad.Plugins/SynExpr/SynComponentInfo.fs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynComponentInfo =
|
||||||
|
let inline createLong (name : LongIdent) =
|
||||||
|
SynComponentInfo.SynComponentInfo ([], None, [], name, PreXmlDoc.Empty, false, None, range0)
|
||||||
|
|
||||||
|
let inline create (name : Ident) = createLong [ name ]
|
||||||
|
|
||||||
|
let inline withDocString (doc : PreXmlDoc) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, _, postfix, access, range) ->
|
||||||
|
SynComponentInfo (attrs, typars, constraints, name, doc, postfix, access, range)
|
||||||
|
|
||||||
|
let inline setGenerics (typars : SynTyparDecls option) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (attrs, _, constraints, name, doc, postfix, access, range) ->
|
||||||
|
SynComponentInfo (attrs, typars, constraints, name, doc, postfix, access, range)
|
||||||
|
|
||||||
|
let inline withGenerics (typars : SynTyparDecl list) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
let inner =
|
||||||
|
if typars.IsEmpty then
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some (SynTyparDecls.PostfixList (typars, [], range0))
|
||||||
|
|
||||||
|
setGenerics inner i
|
||||||
|
|
||||||
|
let inline setAccessibility (acc : SynAccess option) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, doc, postfix, _, range) ->
|
||||||
|
SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, doc, postfix, acc, range)
|
||||||
|
|
||||||
|
let inline withAccessibility (acc : SynAccess) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
setAccessibility (Some acc) i
|
||||||
|
|
||||||
|
let inline addAttributes (attrs : SynAttribute list) (i : SynComponentInfo) : SynComponentInfo =
|
||||||
|
match i with
|
||||||
|
| SynComponentInfo.SynComponentInfo (oldAttrs, typars, constraints, name, doc, postfix, acc, range) ->
|
||||||
|
let attrs =
|
||||||
|
{
|
||||||
|
SynAttributeList.Attributes = attrs
|
||||||
|
SynAttributeList.Range = range0
|
||||||
|
}
|
||||||
|
|
||||||
|
SynComponentInfo.SynComponentInfo ((attrs :: oldAttrs), typars, constraints, name, doc, postfix, acc, range)
|
300
WoofWare.Myriad.Plugins/SynExpr/SynExpr.fs
Normal file
300
WoofWare.Myriad.Plugins/SynExpr/SynExpr.fs
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Myriad.Core
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal SynExprExtensions =
|
||||||
|
type SynExpr with
|
||||||
|
static member CreateConst (s : string) : SynExpr =
|
||||||
|
SynExpr.Const (SynConst.String (s, SynStringKind.Regular, range0), range0)
|
||||||
|
|
||||||
|
static member CreateConst () : SynExpr = SynExpr.Const (SynConst.Unit, range0)
|
||||||
|
|
||||||
|
static member CreateConst (i : int32) : SynExpr =
|
||||||
|
SynExpr.Const (SynConst.Int32 i, range0)
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynExpr =
|
||||||
|
|
||||||
|
/// {f} {x}
|
||||||
|
let applyFunction (f : SynExpr) (x : SynExpr) : SynExpr = SynExpr.CreateApp (f, x)
|
||||||
|
|
||||||
|
/// {f} {x}
|
||||||
|
let inline applyTo (x : SynExpr) (f : SynExpr) : SynExpr = applyFunction f x
|
||||||
|
|
||||||
|
/// {expr} |> {func}
|
||||||
|
let pipeThroughFunction (func : SynExpr) (expr : SynExpr) : SynExpr =
|
||||||
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.pipe, expr)
|
||||||
|
|> applyTo func
|
||||||
|
|
||||||
|
/// if {cond} then {trueBranch} else {falseBranch}
|
||||||
|
/// Note that this function puts the trueBranch last, for pipelining convenience:
|
||||||
|
/// we assume that the `else` branch is more like an error case and is less interesting.
|
||||||
|
let ifThenElse (cond : SynExpr) (falseBranch : SynExpr) (trueBranch : SynExpr) : SynExpr =
|
||||||
|
SynExpr.IfThenElse (
|
||||||
|
cond,
|
||||||
|
trueBranch,
|
||||||
|
Some falseBranch,
|
||||||
|
DebugPointAtBinding.Yes range0,
|
||||||
|
false,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
IfKeyword = range0
|
||||||
|
IsElif = false
|
||||||
|
ThenKeyword = range0
|
||||||
|
ElseKeyword = Some range0
|
||||||
|
IfToThenRange = range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/// try {body} with | {exc} as exc -> {handler}
|
||||||
|
let pipeThroughTryWith (exc : SynPat) (handler : SynExpr) (body : SynExpr) : SynExpr =
|
||||||
|
let clause =
|
||||||
|
SynMatchClause.create (SynPat.As (exc, SynPat.named "exc", range0)) handler
|
||||||
|
|
||||||
|
SynExpr.TryWith (
|
||||||
|
body,
|
||||||
|
[ clause ],
|
||||||
|
range0,
|
||||||
|
DebugPointAtTry.Yes range0,
|
||||||
|
DebugPointAtWith.Yes range0,
|
||||||
|
{
|
||||||
|
TryKeyword = range0
|
||||||
|
TryToWithRange = range0
|
||||||
|
WithKeyword = range0
|
||||||
|
WithToEndRange = range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/// {a} = {b}
|
||||||
|
let equals (a : SynExpr) (b : SynExpr) =
|
||||||
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.eq, a) |> applyTo b
|
||||||
|
|
||||||
|
/// {a} + {b}
|
||||||
|
let plus (a : SynExpr) (b : SynExpr) =
|
||||||
|
SynExpr.CreateAppInfix (
|
||||||
|
SynExpr.CreateLongIdent (
|
||||||
|
SynLongIdent.SynLongIdent (
|
||||||
|
Ident.CreateLong "op_Addition",
|
||||||
|
[],
|
||||||
|
[ Some (IdentTrivia.OriginalNotation "+") ]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
a
|
||||||
|
)
|
||||||
|
|> applyTo b
|
||||||
|
|
||||||
|
let rec stripOptionalParen (expr : SynExpr) : SynExpr =
|
||||||
|
match expr with
|
||||||
|
| SynExpr.Paren (expr, _, _, _) -> stripOptionalParen expr
|
||||||
|
| expr -> expr
|
||||||
|
|
||||||
|
/// {obj}.{meth} {arg}
|
||||||
|
let callMethodArg (meth : string) (arg : SynExpr) (obj : SynExpr) : SynExpr =
|
||||||
|
SynExpr.DotGet (
|
||||||
|
obj,
|
||||||
|
range0,
|
||||||
|
SynLongIdent.SynLongIdent (id = [ Ident.create meth ], dotRanges = [], trivia = [ None ]),
|
||||||
|
range0
|
||||||
|
)
|
||||||
|
|> applyTo arg
|
||||||
|
|
||||||
|
/// {obj}.{meth}()
|
||||||
|
let callMethod (meth : string) (obj : SynExpr) : SynExpr =
|
||||||
|
callMethodArg meth (SynExpr.CreateConst ()) obj
|
||||||
|
|
||||||
|
let callGenericMethod (meth : string) (ty : LongIdent) (obj : SynExpr) : SynExpr =
|
||||||
|
SynExpr.TypeApp (
|
||||||
|
SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0),
|
||||||
|
range0,
|
||||||
|
[ SynType.LongIdent (SynLongIdent.create ty) ],
|
||||||
|
[],
|
||||||
|
Some range0,
|
||||||
|
range0,
|
||||||
|
range0
|
||||||
|
)
|
||||||
|
|> applyTo (SynExpr.CreateConst ())
|
||||||
|
|
||||||
|
/// {obj}.{meth}<ty>()
|
||||||
|
let callGenericMethod' (meth : string) (ty : string) (obj : SynExpr) : SynExpr =
|
||||||
|
SynExpr.TypeApp (
|
||||||
|
SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0),
|
||||||
|
range0,
|
||||||
|
[ SynType.createLongIdent' [ ty ] ],
|
||||||
|
[],
|
||||||
|
Some range0,
|
||||||
|
range0,
|
||||||
|
range0
|
||||||
|
)
|
||||||
|
|> applyTo (SynExpr.CreateConst ())
|
||||||
|
|
||||||
|
let inline index (property : SynExpr) (obj : SynExpr) : SynExpr =
|
||||||
|
SynExpr.DotIndexedGet (obj, property, range0, range0)
|
||||||
|
|
||||||
|
let inline paren (e : SynExpr) : SynExpr =
|
||||||
|
SynExpr.Paren (e, range0, Some range0, range0)
|
||||||
|
|
||||||
|
/// (fun {varName} -> {body})
|
||||||
|
let createLambda (varName : string) (body : SynExpr) : SynExpr =
|
||||||
|
let parsedDataPat = [ SynPat.named varName ]
|
||||||
|
|
||||||
|
SynExpr.Lambda (
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
SynSimplePats.Create [ SynSimplePat.CreateId (Ident.Create varName) ],
|
||||||
|
body,
|
||||||
|
Some (parsedDataPat, body),
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
ArrowRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> paren
|
||||||
|
|
||||||
|
let createThunk (body : SynExpr) : SynExpr =
|
||||||
|
SynExpr.Lambda (
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
SynSimplePats.Create [],
|
||||||
|
body,
|
||||||
|
Some ([ SynPat.unit ], body),
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
ArrowRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> paren
|
||||||
|
|
||||||
|
let inline createIdent (s : string) : SynExpr = SynExpr.Ident (Ident (s, range0))
|
||||||
|
|
||||||
|
let inline createIdent' (i : Ident) : SynExpr = SynExpr.Ident i
|
||||||
|
|
||||||
|
let inline createLongIdent' (ident : Ident list) : SynExpr =
|
||||||
|
SynExpr.LongIdent (false, SynLongIdent.create ident, None, range0)
|
||||||
|
|
||||||
|
let inline createLongIdent (ident : string list) : SynExpr =
|
||||||
|
createLongIdent' (ident |> List.map Ident.create)
|
||||||
|
|
||||||
|
let tupleNoParen (args : SynExpr list) : SynExpr =
|
||||||
|
SynExpr.Tuple (false, args, List.replicate (args.Length - 1) range0, range0)
|
||||||
|
|
||||||
|
let inline tuple (args : SynExpr list) = args |> tupleNoParen |> paren
|
||||||
|
|
||||||
|
/// {body} |> fun a -> Async.StartAsTask (a, ?cancellationToken=ct)
|
||||||
|
let startAsTask (ct : Ident) (body : SynExpr) =
|
||||||
|
let lambda =
|
||||||
|
[
|
||||||
|
createIdent "a"
|
||||||
|
equals
|
||||||
|
(SynExpr.LongIdent (true, SynLongIdent.createS "cancellationToken", None, range0))
|
||||||
|
(createIdent' ct)
|
||||||
|
]
|
||||||
|
|> tuple
|
||||||
|
|> applyFunction (createLongIdent [ "Async" ; "StartAsTask" ])
|
||||||
|
|> createLambda "a"
|
||||||
|
|
||||||
|
pipeThroughFunction lambda body
|
||||||
|
|
||||||
|
let inline createLet (bindings : SynBinding list) (body : SynExpr) : SynExpr =
|
||||||
|
SynExpr.LetOrUse (false, false, bindings, body, range0, SynExprLetOrUseTrivia.empty)
|
||||||
|
|
||||||
|
let inline createMatch (matchOn : SynExpr) (cases : SynMatchClause list) : SynExpr =
|
||||||
|
SynExpr.Match (
|
||||||
|
DebugPointAtBinding.Yes range0,
|
||||||
|
matchOn,
|
||||||
|
cases,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
MatchKeyword = range0
|
||||||
|
WithKeyword = range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let typeAnnotate (ty : SynType) (expr : SynExpr) : SynExpr = SynExpr.Typed (expr, ty, range0)
|
||||||
|
|
||||||
|
let inline createNew (ty : SynType) (args : SynExpr) : SynExpr =
|
||||||
|
SynExpr.New (false, ty, paren args, range0)
|
||||||
|
|
||||||
|
let inline createWhile (cond : SynExpr) (body : SynExpr) : SynExpr =
|
||||||
|
SynExpr.While (DebugPointAtWhile.Yes range0, cond, body, range0)
|
||||||
|
|
||||||
|
let inline createNull () : SynExpr = SynExpr.Null range0
|
||||||
|
|
||||||
|
let reraise : SynExpr = createIdent "reraise" |> applyTo (SynExpr.CreateConst ())
|
||||||
|
|
||||||
|
let sequential (exprs : SynExpr list) : SynExpr =
|
||||||
|
exprs
|
||||||
|
|> List.reduce (fun a b -> SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, false, a, b, range0))
|
||||||
|
|
||||||
|
/// {compExpr} { {lets} ; return {ret} }
|
||||||
|
let createCompExpr (compExpr : string) (retBody : SynExpr) (lets : CompExprBinding list) : SynExpr =
|
||||||
|
let retStatement = SynExpr.YieldOrReturn ((false, true), retBody, range0)
|
||||||
|
|
||||||
|
let contents : SynExpr =
|
||||||
|
(retStatement, List.rev lets)
|
||||||
|
||> List.fold (fun state binding ->
|
||||||
|
match binding with
|
||||||
|
| LetBang (lhs, rhs) ->
|
||||||
|
SynExpr.LetOrUseBang (
|
||||||
|
DebugPointAtBinding.Yes range0,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
SynPat.named lhs,
|
||||||
|
rhs,
|
||||||
|
[],
|
||||||
|
state,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
EqualsRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
| Let (lhs, rhs) -> createLet [ SynBinding.basic [ Ident.create lhs ] [] rhs ] state
|
||||||
|
| Use (lhs, rhs) ->
|
||||||
|
SynExpr.LetOrUse (
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
[ SynBinding.basic [ Ident.create lhs ] [] rhs ],
|
||||||
|
state,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
SynExprLetOrUseTrivia.InKeyword = None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
| Do body -> sequential [ SynExpr.Do (body, range0) ; state ]
|
||||||
|
)
|
||||||
|
|
||||||
|
applyFunction (createIdent compExpr) (SynExpr.ComputationExpr (false, contents, range0))
|
||||||
|
|
||||||
|
/// {expr} |> Async.AwaitTask
|
||||||
|
let awaitTask (expr : SynExpr) : SynExpr =
|
||||||
|
expr |> pipeThroughFunction (createLongIdent [ "Async" ; "AwaitTask" ])
|
||||||
|
|
||||||
|
/// {ident}.ToString ()
|
||||||
|
/// with special casing for some types like DateTime
|
||||||
|
let toString (ty : SynType) (ident : SynExpr) =
|
||||||
|
match ty with
|
||||||
|
| DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-dd")
|
||||||
|
| DateTime -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-ddTHH:mm:ss")
|
||||||
|
| _ -> callMethod "ToString" ident
|
||||||
|
|
||||||
|
let upcast' (ty : SynType) (e : SynExpr) = SynExpr.Upcast (e, ty, range0)
|
||||||
|
|
||||||
|
/// {ident} - {rhs}
|
||||||
|
let minus (ident : SynLongIdent) (rhs : SynExpr) : SynExpr =
|
||||||
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.sub, SynExpr.CreateLongIdent ident)
|
||||||
|
|> applyTo rhs
|
||||||
|
|
||||||
|
/// {ident} - {n}
|
||||||
|
let minusN (ident : SynLongIdent) (n : int) : SynExpr = minus ident (SynExpr.CreateConst n)
|
||||||
|
|
||||||
|
/// {y} > {x}
|
||||||
|
let greaterThan (x : SynExpr) (y : SynExpr) : SynExpr =
|
||||||
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.ge, y) |> applyTo x
|
||||||
|
|
||||||
|
/// {y} >= {x}
|
||||||
|
let greaterThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr =
|
||||||
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.geq, y)
|
||||||
|
|> applyTo x
|
10
WoofWare.Myriad.Plugins/SynExpr/SynExprLetOrUseTrivia.fs
Normal file
10
WoofWare.Myriad.Plugins/SynExpr/SynExprLetOrUseTrivia.fs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynExprLetOrUseTrivia =
|
||||||
|
let empty : SynExprLetOrUseTrivia =
|
||||||
|
{
|
||||||
|
InKeyword = None
|
||||||
|
}
|
69
WoofWare.Myriad.Plugins/SynExpr/SynField.fs
Normal file
69
WoofWare.Myriad.Plugins/SynExpr/SynField.fs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
|
||||||
|
type internal SynFieldData<'Ident> =
|
||||||
|
{
|
||||||
|
Attrs : SynAttribute list
|
||||||
|
Ident : 'Ident
|
||||||
|
Type : SynType
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynField =
|
||||||
|
/// Get the useful information out of a SynField.
|
||||||
|
let extract (SynField (attrs, _, id, fieldType, _, _, _, _, _)) : SynFieldData<Ident option> =
|
||||||
|
{
|
||||||
|
Attrs = attrs |> List.collect (fun l -> l.Attributes)
|
||||||
|
Ident = id
|
||||||
|
Type = fieldType
|
||||||
|
}
|
||||||
|
|
||||||
|
let mapIdent<'a, 'b> (f : 'a -> 'b) (x : SynFieldData<'a>) : SynFieldData<'b> =
|
||||||
|
let ident = f x.Ident
|
||||||
|
|
||||||
|
{
|
||||||
|
Attrs = x.Attrs
|
||||||
|
Ident = ident
|
||||||
|
Type = x.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Throws if the field has no identifier.
|
||||||
|
let extractWithIdent (f : SynField) : SynFieldData<Ident> =
|
||||||
|
f
|
||||||
|
|> extract
|
||||||
|
|> mapIdent (fun ident ->
|
||||||
|
match ident with
|
||||||
|
| None -> failwith "expected field identifier to have a value, but it did not"
|
||||||
|
| Some i -> i
|
||||||
|
)
|
||||||
|
|
||||||
|
let make (data : SynFieldData<Ident option>) : SynField =
|
||||||
|
let attrs : SynAttributeList list =
|
||||||
|
data.Attrs
|
||||||
|
|> List.map (fun l ->
|
||||||
|
{
|
||||||
|
Attributes = [ l ]
|
||||||
|
Range = range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
SynField.SynField (
|
||||||
|
attrs,
|
||||||
|
false,
|
||||||
|
data.Ident,
|
||||||
|
data.Type,
|
||||||
|
false,
|
||||||
|
PreXmlDoc.Empty,
|
||||||
|
None,
|
||||||
|
range0,
|
||||||
|
SynFieldTrivia.Zero
|
||||||
|
)
|
||||||
|
|
||||||
|
let withDocString (doc : PreXmlDoc) (f : SynField) : SynField =
|
||||||
|
match f with
|
||||||
|
| SynField (attributes, isStatic, idOpt, fieldType, isMutable, _, accessibility, range, trivia) ->
|
||||||
|
SynField (attributes, isStatic, idOpt, fieldType, isMutable, doc, accessibility, range, trivia)
|
106
WoofWare.Myriad.Plugins/SynExpr/SynLongIdent.fs
Normal file
106
WoofWare.Myriad.Plugins/SynExpr/SynLongIdent.fs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynLongIdent =
|
||||||
|
|
||||||
|
let geq =
|
||||||
|
SynLongIdent.SynLongIdent (
|
||||||
|
[ Ident.create "op_GreaterThanOrEqual" ],
|
||||||
|
[],
|
||||||
|
[ Some (IdentTrivia.OriginalNotation ">=") ]
|
||||||
|
)
|
||||||
|
|
||||||
|
let ge =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_GreaterThan" ], [], [ Some (IdentTrivia.OriginalNotation ">") ])
|
||||||
|
|
||||||
|
let sub =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_Subtraction" ], [], [ Some (IdentTrivia.OriginalNotation "-") ])
|
||||||
|
|
||||||
|
let eq =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_Equality" ], [], [ Some (IdentTrivia.OriginalNotation "=") ])
|
||||||
|
|
||||||
|
let pipe =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_PipeRight" ], [], [ Some (IdentTrivia.OriginalNotation "|>") ])
|
||||||
|
|
||||||
|
let toString (sli : SynLongIdent) : string =
|
||||||
|
sli.LongIdent |> List.map _.idText |> String.concat "."
|
||||||
|
|
||||||
|
let create (ident : LongIdent) : SynLongIdent =
|
||||||
|
let commas =
|
||||||
|
match ident with
|
||||||
|
| [] -> []
|
||||||
|
| _ :: commas -> commas |> List.map (fun _ -> range0)
|
||||||
|
|
||||||
|
SynLongIdent.SynLongIdent (ident, commas, List.replicate ident.Length None)
|
||||||
|
|
||||||
|
let inline createI (i : Ident) : SynLongIdent = create [ i ]
|
||||||
|
|
||||||
|
let inline createS (s : string) : SynLongIdent = createI (Ident (s, range0))
|
||||||
|
|
||||||
|
let inline createS' (s : string list) : SynLongIdent =
|
||||||
|
create (s |> List.map (fun i -> Ident (i, range0)))
|
||||||
|
|
||||||
|
let isUnit (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when System.String.Equals (i.idText, "unit", System.StringComparison.OrdinalIgnoreCase) -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isList (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true
|
||||||
|
// TODO: consider FSharpList or whatever it is
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isArray (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when
|
||||||
|
System.String.Equals (i.idText, "array", System.StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| System.String.Equals (i.idText, "[]", System.StringComparison.Ordinal)
|
||||||
|
->
|
||||||
|
true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isOption (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] when System.String.Equals (i.idText, "option", System.StringComparison.OrdinalIgnoreCase) -> true
|
||||||
|
// TODO: consider Microsoft.FSharp.Option or whatever it is
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isResponse (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "Response" ]
|
||||||
|
| [ "RestEase" ; "Response" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isMap (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "Map" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isReadOnlyDictionary (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "IReadOnlyDictionary" ]
|
||||||
|
| [ "Generic" ; "IReadOnlyDictionary" ]
|
||||||
|
| [ "Collections" ; "Generic" ; "IReadOnlyDictionary" ]
|
||||||
|
| [ "System" ; "Collections" ; "Generic" ; "IReadOnlyDictionary" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isDictionary (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "Dictionary" ]
|
||||||
|
| [ "Generic" ; "Dictionary" ]
|
||||||
|
| [ "Collections" ; "Generic" ; "Dictionary" ]
|
||||||
|
| [ "System" ; "Collections" ; "Generic" ; "Dictionary" ] -> true
|
||||||
|
| _ -> false
|
||||||
|
|
||||||
|
let isIDictionary (ident : SynLongIdent) : bool =
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "IDictionary" ]
|
||||||
|
| [ "Generic" ; "IDictionary" ]
|
||||||
|
| [ "Collections" ; "Generic" ; "IDictionary" ]
|
||||||
|
| [ "System" ; "Collections" ; "Generic" ; "IDictionary" ] -> true
|
||||||
|
| _ -> false
|
24
WoofWare.Myriad.Plugins/SynExpr/SynMatchClause.fs
Normal file
24
WoofWare.Myriad.Plugins/SynExpr/SynMatchClause.fs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynMatchClause =
|
||||||
|
let create (lhs : SynPat) (rhs : SynExpr) : SynMatchClause =
|
||||||
|
SynMatchClause.SynMatchClause (
|
||||||
|
lhs,
|
||||||
|
None,
|
||||||
|
rhs,
|
||||||
|
range0,
|
||||||
|
DebugPointAtTarget.Yes,
|
||||||
|
{
|
||||||
|
ArrowRange = Some range0
|
||||||
|
BarRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let withWhere (where : SynExpr) (m : SynMatchClause) : SynMatchClause =
|
||||||
|
match m with
|
||||||
|
| SynMatchClause (synPat, _, resultExpr, range, debugPointAtTarget, synMatchClauseTrivia) ->
|
||||||
|
SynMatchClause (synPat, Some where, resultExpr, range, debugPointAtTarget, synMatchClauseTrivia)
|
65
WoofWare.Myriad.Plugins/SynExpr/SynMemberDefn.fs
Normal file
65
WoofWare.Myriad.Plugins/SynExpr/SynMemberDefn.fs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynMemberDefn =
|
||||||
|
let private interfaceMemberSlotFlags =
|
||||||
|
{
|
||||||
|
SynMemberFlags.IsInstance = true
|
||||||
|
SynMemberFlags.IsDispatchSlot = true
|
||||||
|
SynMemberFlags.IsOverrideOrExplicitImpl = false
|
||||||
|
SynMemberFlags.IsFinal = false
|
||||||
|
SynMemberFlags.GetterOrSetterIsCompilerGenerated = false
|
||||||
|
SynMemberFlags.MemberKind = SynMemberKind.Member
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let abstractMember
|
||||||
|
(ident : SynIdent)
|
||||||
|
(typars : SynTyparDecls option)
|
||||||
|
(arity : SynValInfo)
|
||||||
|
(xmlDoc : PreXmlDoc)
|
||||||
|
(returnType : SynType)
|
||||||
|
: SynMemberDefn
|
||||||
|
=
|
||||||
|
let slot =
|
||||||
|
SynValSig.SynValSig (
|
||||||
|
[],
|
||||||
|
ident,
|
||||||
|
SynValTyparDecls.SynValTyparDecls (typars, true),
|
||||||
|
returnType,
|
||||||
|
arity,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
xmlDoc,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
EqualsRange = None
|
||||||
|
WithKeyword = None
|
||||||
|
InlineKeyword = None
|
||||||
|
LeadingKeyword = SynLeadingKeyword.Abstract range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
SynMemberDefn.AbstractSlot (
|
||||||
|
slot,
|
||||||
|
interfaceMemberSlotFlags,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
GetSetKeywords = None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let staticMember (binding : SynBinding) : SynMemberDefn =
|
||||||
|
let binding = SynBinding.makeStaticMember binding
|
||||||
|
SynMemberDefn.Member (binding, range0)
|
||||||
|
|
||||||
|
let memberImplementation (binding : SynBinding) : SynMemberDefn =
|
||||||
|
let binding = SynBinding.makeInstanceMember binding
|
||||||
|
SynMemberDefn.Member (binding, range0)
|
28
WoofWare.Myriad.Plugins/SynExpr/SynModuleDecl.fs
Normal file
28
WoofWare.Myriad.Plugins/SynExpr/SynModuleDecl.fs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynModuleDecl =
|
||||||
|
|
||||||
|
let inline openAny (ident : SynOpenDeclTarget) : SynModuleDecl = SynModuleDecl.Open (ident, range0)
|
||||||
|
|
||||||
|
let inline createLets (bindings : SynBinding list) : SynModuleDecl =
|
||||||
|
SynModuleDecl.Let (false, bindings, range0)
|
||||||
|
|
||||||
|
let inline createLet (binding : SynBinding) : SynModuleDecl = createLets [ binding ]
|
||||||
|
|
||||||
|
let nestedModule (info : SynComponentInfo) (decls : SynModuleDecl list) : SynModuleDecl =
|
||||||
|
SynModuleDecl.NestedModule (
|
||||||
|
info,
|
||||||
|
false,
|
||||||
|
decls,
|
||||||
|
false,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
ModuleKeyword = Some range0
|
||||||
|
EqualsRange = Some range0
|
||||||
|
}
|
||||||
|
)
|
24
WoofWare.Myriad.Plugins/SynExpr/SynModuleOrNamespace.fs
Normal file
24
WoofWare.Myriad.Plugins/SynExpr/SynModuleOrNamespace.fs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Xml
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynModuleOrNamespace =
|
||||||
|
|
||||||
|
let createNamespace (name : LongIdent) (decls : SynModuleDecl list) =
|
||||||
|
SynModuleOrNamespace.SynModuleOrNamespace (
|
||||||
|
name,
|
||||||
|
false,
|
||||||
|
SynModuleOrNamespaceKind.DeclaredNamespace,
|
||||||
|
decls,
|
||||||
|
PreXmlDoc.Empty,
|
||||||
|
[],
|
||||||
|
None,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.Namespace range0
|
||||||
|
}
|
||||||
|
)
|
35
WoofWare.Myriad.Plugins/SynExpr/SynPat.fs
Normal file
35
WoofWare.Myriad.Plugins/SynExpr/SynPat.fs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynPat =
|
||||||
|
let inline paren (pat : SynPat) : SynPat = SynPat.Paren (pat, range0)
|
||||||
|
|
||||||
|
let inline annotateTypeNoParen (ty : SynType) (pat : SynPat) = SynPat.Typed (pat, ty, range0)
|
||||||
|
|
||||||
|
let inline annotateType (ty : SynType) (pat : SynPat) = paren (annotateTypeNoParen ty pat)
|
||||||
|
|
||||||
|
let inline named (s : string) : SynPat =
|
||||||
|
SynPat.Named (SynIdent.SynIdent (Ident (s, range0), None), false, None, range0)
|
||||||
|
|
||||||
|
let inline namedI (i : Ident) : SynPat =
|
||||||
|
SynPat.Named (SynIdent.SynIdent (i, None), false, None, range0)
|
||||||
|
|
||||||
|
let inline identWithArgs (i : LongIdent) (args : SynArgPats) : SynPat =
|
||||||
|
SynPat.LongIdent (SynLongIdent.create i, None, None, args, None, range0)
|
||||||
|
|
||||||
|
let inline tupleNoParen (elements : SynPat list) : SynPat =
|
||||||
|
match elements with
|
||||||
|
| [] -> failwith "Can't tuple no elements in a pattern"
|
||||||
|
| [ p ] -> p
|
||||||
|
| elements -> SynPat.Tuple (false, elements, List.replicate (elements.Length - 1) range0, range0)
|
||||||
|
|
||||||
|
let inline tuple (elements : SynPat list) : SynPat = tupleNoParen elements |> paren
|
||||||
|
|
||||||
|
let inline createConst (c : SynConst) = SynPat.Const (c, range0)
|
||||||
|
|
||||||
|
let unit = createConst SynConst.Unit
|
||||||
|
|
||||||
|
let createNull = SynPat.Null range0
|
239
WoofWare.Myriad.Plugins/SynExpr/SynType.fs
Normal file
239
WoofWare.Myriad.Plugins/SynExpr/SynType.fs
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynType =
|
||||||
|
let rec stripOptionalParen (ty : SynType) : SynType =
|
||||||
|
match ty with
|
||||||
|
| SynType.Paren (ty, _) -> stripOptionalParen ty
|
||||||
|
| ty -> ty
|
||||||
|
|
||||||
|
let inline createLongIdent (ident : LongIdent) : SynType =
|
||||||
|
SynType.LongIdent (SynLongIdent.create ident)
|
||||||
|
|
||||||
|
let inline createLongIdent' (ident : string list) : SynType =
|
||||||
|
SynType.LongIdent (SynLongIdent.createS' ident)
|
||||||
|
|
||||||
|
let inline named (name : string) = createLongIdent' [ name ]
|
||||||
|
|
||||||
|
let inline app' (name : SynType) (args : SynType list) : SynType =
|
||||||
|
if args.IsEmpty then
|
||||||
|
failwith "Type cannot be applied to no arguments"
|
||||||
|
|
||||||
|
SynType.App (name, Some range0, args, List.replicate (args.Length - 1) range0, Some range0, false, range0)
|
||||||
|
|
||||||
|
let inline app (name : string) (args : SynType list) : SynType = app' (named name) args
|
||||||
|
|
||||||
|
let inline appPostfix (name : string) (arg : SynType) : SynType =
|
||||||
|
SynType.App (named name, None, [ arg ], [], None, true, range0)
|
||||||
|
|
||||||
|
let inline funFromDomain (domain : SynType) (range : SynType) : SynType =
|
||||||
|
SynType.Fun (
|
||||||
|
domain,
|
||||||
|
range,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
ArrowRange = range0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let inline signatureParamOfType (ty : SynType) (name : Ident option) : SynType =
|
||||||
|
SynType.SignatureParameter ([], false, name, ty, range0)
|
||||||
|
|
||||||
|
let inline var (ty : SynTypar) : SynType = SynType.Var (ty, range0)
|
||||||
|
|
||||||
|
let unit : SynType = named "unit"
|
||||||
|
let int : SynType = named "int"
|
||||||
|
|
||||||
|
/// Given ['a1, 'a2] and 'ret, returns 'a1 -> 'a2 -> 'ret.
|
||||||
|
let toFun (inputs : SynType list) (ret : SynType) : SynType =
|
||||||
|
(ret, List.rev inputs) ||> List.fold (fun ty input -> funFromDomain input ty)
|
||||||
|
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal SynTypePatterns =
|
||||||
|
let (|OptionType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isOption ident ->
|
||||||
|
Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|UnitType|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident when SynLongIdent.isUnit ident -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|ListType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isList ident ->
|
||||||
|
Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|ArrayType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isArray ident ->
|
||||||
|
Some innerType
|
||||||
|
| SynType.Array (1, innerType, _) -> Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|RestEaseResponseType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isResponse ident ->
|
||||||
|
Some innerType
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|DictionaryType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isDictionary ident ->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|IDictionaryType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isIDictionary ident ->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|IReadOnlyDictionaryType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when
|
||||||
|
SynLongIdent.isReadOnlyDictionary ident
|
||||||
|
->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|MapType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isMap ident ->
|
||||||
|
Some (key, value)
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|BigInt|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map _.idText with
|
||||||
|
| [ "bigint" ]
|
||||||
|
| [ "BigInteger" ]
|
||||||
|
| [ "Numerics" ; "BigInteger" ]
|
||||||
|
| [ "System" ; "Numerics" ; "BigInteger" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
/// Returns the type, qualified as in e.g. `System.Boolean`.
|
||||||
|
let (|PrimitiveType|_|) (fieldType : SynType) : LongIdent option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] -> Primitives.qualifyType i.idText
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|String|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] ->
|
||||||
|
[ "string" ]
|
||||||
|
|> List.tryFind (fun s -> s = i.idText)
|
||||||
|
|> Option.map ignore<string>
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Byte|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] -> [ "byte" ] |> List.tryFind (fun s -> s = i.idText) |> Option.map ignore<string>
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Guid|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Guid" ]
|
||||||
|
| [ "Guid" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|HttpResponseMessage|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Net" ; "Http" ; "HttpResponseMessage" ]
|
||||||
|
| [ "Net" ; "Http" ; "HttpResponseMessage" ]
|
||||||
|
| [ "Http" ; "HttpResponseMessage" ]
|
||||||
|
| [ "HttpResponseMessage" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|HttpContent|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Net" ; "Http" ; "HttpContent" ]
|
||||||
|
| [ "Net" ; "Http" ; "HttpContent" ]
|
||||||
|
| [ "Http" ; "HttpContent" ]
|
||||||
|
| [ "HttpContent" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Stream|_|) (fieldType : SynType) : unit option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "IO" ; "Stream" ]
|
||||||
|
| [ "IO" ; "Stream" ]
|
||||||
|
| [ "Stream" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|NumberType|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent ident ->
|
||||||
|
match ident.LongIdent with
|
||||||
|
| [ i ] -> [ "string" ; "float" ; "int" ; "bool" ] |> List.tryFind (fun s -> s = i.idText)
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|DateOnly|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "DateOnly" ]
|
||||||
|
| [ "DateOnly" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|DateTime|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "DateTime" ]
|
||||||
|
| [ "DateTime" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Uri|_|) (fieldType : SynType) =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "System" ; "Uri" ]
|
||||||
|
| [ "Uri" ] -> Some ()
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|Task|_|) (fieldType : SynType) : SynType option =
|
||||||
|
match fieldType with
|
||||||
|
| SynType.App (SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)), _, args, _, _, _, _) ->
|
||||||
|
match ident |> List.map (fun i -> i.idText) with
|
||||||
|
| [ "Task" ]
|
||||||
|
| [ "Tasks" ; "Task" ]
|
||||||
|
| [ "Threading" ; "Tasks" ; "Task" ]
|
||||||
|
| [ "System" ; "Threading" ; "Tasks" ; "Task" ] ->
|
||||||
|
match args with
|
||||||
|
| [ arg ] -> Some arg
|
||||||
|
| _ -> failwithf "Expected Task to be applied to exactly one arg, but got: %+A" args
|
||||||
|
| _ -> None
|
||||||
|
| _ -> None
|
27
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefn.fs
Normal file
27
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefn.fs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.SyntaxTrivia
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynTypeDefn =
|
||||||
|
|
||||||
|
let inline create (componentInfo : SynComponentInfo) (repr : SynTypeDefnRepr) : SynTypeDefn =
|
||||||
|
SynTypeDefn.SynTypeDefn (
|
||||||
|
componentInfo,
|
||||||
|
repr,
|
||||||
|
[],
|
||||||
|
None,
|
||||||
|
range0,
|
||||||
|
{
|
||||||
|
LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0
|
||||||
|
EqualsRange = Some range0
|
||||||
|
WithKeyword = None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let inline withMemberDefns (members : SynMemberDefn list) (r : SynTypeDefn) : SynTypeDefn =
|
||||||
|
match r with
|
||||||
|
| SynTypeDefn (typeInfo, typeRepr, _, ctor, range, trivia) ->
|
||||||
|
SynTypeDefn.SynTypeDefn (typeInfo, typeRepr, members, ctor, range, trivia)
|
20
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefnRepr.fs
Normal file
20
WoofWare.Myriad.Plugins/SynExpr/SynTypeDefnRepr.fs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
open Fantomas.FCS.Text.Range
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynTypeDefnRepr =
|
||||||
|
|
||||||
|
let inline interfaceType (mems : SynMemberDefns) : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Unspecified, mems, range0)
|
||||||
|
|
||||||
|
/// Indicates the body of a `type Foo with {body}` extension type declaration.
|
||||||
|
let inline augmentation () : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0)
|
||||||
|
|
||||||
|
let inline union (cases : SynUnionCase list) : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (None, cases, range0), range0)
|
||||||
|
|
||||||
|
let inline record (fields : SynField list) : SynTypeDefnRepr =
|
||||||
|
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, fields, range0), range0)
|
41
WoofWare.Myriad.Plugins/SynExpr/SynUnionCase.fs
Normal file
41
WoofWare.Myriad.Plugins/SynExpr/SynUnionCase.fs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
namespace WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
open Fantomas.FCS.Syntax
|
||||||
|
|
||||||
|
type internal UnionCase<'Ident> =
|
||||||
|
{
|
||||||
|
Fields : SynFieldData<'Ident> list
|
||||||
|
Attrs : SynAttribute list
|
||||||
|
Ident : Ident
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal UnionCase =
|
||||||
|
let mapIdentFields<'a, 'b> (f : 'a -> 'b) (unionCase : UnionCase<'a>) : UnionCase<'b> =
|
||||||
|
{
|
||||||
|
Fields = unionCase.Fields |> List.map (SynField.mapIdent f)
|
||||||
|
Attrs = unionCase.Attrs
|
||||||
|
Ident = unionCase.Ident
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module internal SynUnionCase =
|
||||||
|
let extract (SynUnionCase (attrs, id, caseType, _, _, _, _)) : UnionCase<Ident option> =
|
||||||
|
match caseType with
|
||||||
|
| SynUnionCaseKind.FullType _ -> failwith "WoofWare.Myriad does not support FullType union cases."
|
||||||
|
| SynUnionCaseKind.Fields fields ->
|
||||||
|
|
||||||
|
let fields = fields |> List.map SynField.extract
|
||||||
|
|
||||||
|
let id =
|
||||||
|
match id with
|
||||||
|
| SynIdent.SynIdent (ident, _) -> ident
|
||||||
|
|
||||||
|
// As far as I can tell, there's no way to get any attributes here? :shrug:
|
||||||
|
let attrs = attrs |> List.collect (fun l -> l.Attributes)
|
||||||
|
|
||||||
|
{
|
||||||
|
Fields = fields
|
||||||
|
Attrs = attrs
|
||||||
|
Ident = id
|
||||||
|
}
|
@@ -1,10 +0,0 @@
|
|||||||
namespace WoofWare.Myriad.Plugins
|
|
||||||
|
|
||||||
open Fantomas.FCS.Syntax
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module internal SynType =
|
|
||||||
let rec stripOptionalParen (ty : SynType) : SynType =
|
|
||||||
match ty with
|
|
||||||
| SynType.Paren (ty, _) -> stripOptionalParen ty
|
|
||||||
| ty -> ty
|
|
@@ -25,11 +25,28 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="List.fs"/>
|
<Compile Include="List.fs"/>
|
||||||
<Compile Include="Ident.fs" />
|
<Compile Include="Primitives.fs" />
|
||||||
<Compile Include="AstHelper.fs"/>
|
<Compile Include="SynExpr\PreXmlDoc.fs" />
|
||||||
<Compile Include="SynExpr.fs"/>
|
<Compile Include="SynExpr\Ident.fs" />
|
||||||
<Compile Include="SynType.fs"/>
|
<Compile Include="SynExpr\SynLongIdent.fs" />
|
||||||
<Compile Include="SynAttribute.fs"/>
|
<Compile Include="SynExpr\SynExprLetOrUseTrivia.fs" />
|
||||||
|
<Compile Include="SynExpr\SynPat.fs" />
|
||||||
|
<Compile Include="SynExpr\SynBinding.fs" />
|
||||||
|
<Compile Include="SynExpr\SynType.fs" />
|
||||||
|
<Compile Include="SynExpr\SynMatchClause.fs" />
|
||||||
|
<Compile Include="SynExpr\CompExpr.fs" />
|
||||||
|
<Compile Include="SynExpr\SynExpr.fs" />
|
||||||
|
<Compile Include="SynExpr\SynArgPats.fs" />
|
||||||
|
<Compile Include="SynExpr\SynField.fs" />
|
||||||
|
<Compile Include="SynExpr\SynUnionCase.fs" />
|
||||||
|
<Compile Include="SynExpr\SynTypeDefnRepr.fs" />
|
||||||
|
<Compile Include="SynExpr\SynTypeDefn.fs" />
|
||||||
|
<Compile Include="SynExpr\SynComponentInfo.fs" />
|
||||||
|
<Compile Include="SynExpr\SynMemberDefn.fs" />
|
||||||
|
<Compile Include="SynExpr\SynAttribute.fs" />
|
||||||
|
<Compile Include="SynExpr\SynModuleDecl.fs" />
|
||||||
|
<Compile Include="SynExpr\SynModuleOrNamespace.fs" />
|
||||||
|
<Compile Include="AstHelper.fs" />
|
||||||
<Compile Include="RemoveOptionsGenerator.fs"/>
|
<Compile Include="RemoveOptionsGenerator.fs"/>
|
||||||
<Compile Include="InterfaceMockGenerator.fs"/>
|
<Compile Include="InterfaceMockGenerator.fs"/>
|
||||||
<Compile Include="JsonSerializeGenerator.fs"/>
|
<Compile Include="JsonSerializeGenerator.fs"/>
|
||||||
|
@@ -3,5 +3,12 @@
|
|||||||
"publicReleaseRefSpec": [
|
"publicReleaseRefSpec": [
|
||||||
"^refs/heads/main$"
|
"^refs/heads/main$"
|
||||||
],
|
],
|
||||||
"pathFilters": null
|
"pathFilters": [
|
||||||
}
|
"./",
|
||||||
|
":/WoofWare.Myriad.Plugins.Attributes",
|
||||||
|
"^:/WoofWare.Myriad.Plugins.Attributes/WoofWare.Myriad.Plugins.Attributes.Test",
|
||||||
|
":/global.json",
|
||||||
|
":/README.md",
|
||||||
|
":/Directory.Build.props"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
@@ -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.10.0]" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
36
flake.nix
36
flake.nix
@@ -7,7 +7,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs = {
|
||||||
self,
|
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
flake-utils,
|
flake-utils,
|
||||||
...
|
...
|
||||||
@@ -46,44 +45,19 @@
|
|||||||
packages = {
|
packages = {
|
||||||
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256;
|
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256;
|
||||||
fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256;
|
fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256;
|
||||||
fetchDeps = let
|
|
||||||
flags = [];
|
|
||||||
runtimeIds = ["win-x64"] ++ map (system: pkgs.dotnetCorePackages.systemToDotnetRid system) dotnet-sdk.meta.platforms;
|
|
||||||
in
|
|
||||||
pkgs.writeShellScriptBin "fetch-${pname}-deps" (builtins.readFile (pkgs.substituteAll {
|
|
||||||
src = ./nix/fetchDeps.sh;
|
|
||||||
pname = pname;
|
|
||||||
binPath = pkgs.lib.makeBinPath [pkgs.coreutils dotnet-sdk (pkgs.nuget-to-nix.override {inherit dotnet-sdk;})];
|
|
||||||
projectFiles = toString ["./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj" "./ConsumePlugin/ConsumePlugin.fsproj" "./WoofWare.Myriad.Plugins.Attributes/WoofWare.Myriad.Plugins.Attributes.fsproj"];
|
|
||||||
testProjectFiles = ["./WoofWare.Myriad.Plugins.Test/WoofWare.Myriad.Plugins.Test.fsproj" "./WoofWare.Myriad.Plugins.Attributes/Test/Woofware.Myriad.Plugins.Attributes.Test.fsproj"];
|
|
||||||
rids = pkgs.lib.concatStringsSep "\" \"" runtimeIds;
|
|
||||||
packages = dotnet-sdk.packages;
|
|
||||||
storeSrc = pkgs.srcOnly {
|
|
||||||
src = ./.;
|
|
||||||
pname = pname;
|
|
||||||
version = version;
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
default = pkgs.buildDotnetModule {
|
default = pkgs.buildDotnetModule {
|
||||||
pname = pname;
|
inherit pname version dotnet-sdk dotnet-runtime;
|
||||||
name = "WoofWare.Myriad.Plugins";
|
name = "WoofWare.Myriad.Plugins";
|
||||||
version = version;
|
|
||||||
src = ./.;
|
src = ./.;
|
||||||
projectFile = "./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj";
|
projectFile = "./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj";
|
||||||
nugetDeps = ./nix/deps.nix;
|
testProjectFile = "./WoofWare.Myriad.Plugins.Test/WoofWare.Myriad.Plugins.Test.fsproj";
|
||||||
|
disabledTests = ["WoofWare.Myriad.Plugins.Test.TestSurface.CheckVersionAgainstRemote"];
|
||||||
|
nugetDeps = ./nix/deps.nix; # `nix build .#default.passthru.fetch-deps && ./result` and put the result here
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
dotnet-sdk = dotnet-sdk;
|
|
||||||
dotnet-runtime = dotnet-runtime;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
buildInputs = with pkgs; [
|
buildInputs = [dotnet-sdk];
|
||||||
(with dotnetCorePackages;
|
|
||||||
combinePackages [
|
|
||||||
dotnet-sdk_8
|
|
||||||
dotnetPackages.Nuget
|
|
||||||
])
|
|
||||||
];
|
|
||||||
packages = [
|
packages = [
|
||||||
pkgs.alejandra
|
pkgs.alejandra
|
||||||
pkgs.nodePackages.markdown-link-check
|
pkgs.nodePackages.markdown-link-check
|
||||||
|
189
nix/deps.nix
189
nix/deps.nix
@@ -1,20 +1,15 @@
|
|||||||
# This file was automatically generated by passthru.fetch-deps.
|
# This file was automatically generated by passthru.fetch-deps.
|
||||||
# Please don't edit it manually, your changes might get overwritten!
|
# Please dont edit it manually, your changes might get overwritten!
|
||||||
{fetchNuGet}: [
|
{fetchNuGet}: [
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "fsharp-analyzers";
|
pname = "ApiSurface";
|
||||||
version = "0.25.0";
|
version = "4.0.41";
|
||||||
sha256 = "sha256-njfJYi40jNvrD+mgu9LtQw2Omh8P1SSDThesozH0KQY=";
|
sha256 = "03kfa5ngmgkik9lc58sp8s9rrh9g40hhgjnrv662ks0d0y2i9i89";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "fantomas";
|
pname = "fantomas";
|
||||||
version = "6.3.0-alpha-008";
|
version = "6.3.9";
|
||||||
sha256 = "sha256-rI/4upuj8JBy2C9gl2lwI/JXmBD7UHKxCoSpd+bstRw=";
|
sha256 = "1b34iiiff02bbzjv03zyna8xmrgs6y87zdvp5i5k58fcqpjw44sx";
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "ApiSurface";
|
|
||||||
version = "4.0.33";
|
|
||||||
sha256 = "0mmsa5gxfd3bbgacip0c1hljwd958zcx1012qdh033sx6nfz3v36";
|
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Fantomas.Core";
|
pname = "Fantomas.Core";
|
||||||
@@ -31,6 +26,11 @@
|
|||||||
version = "2.16.6";
|
version = "2.16.6";
|
||||||
sha256 = "176rwky6b5rk8dzldiz4068p7m9c5y9ygzbhadrs14jkl94pc56n";
|
sha256 = "176rwky6b5rk8dzldiz4068p7m9c5y9ygzbhadrs14jkl94pc56n";
|
||||||
})
|
})
|
||||||
|
(fetchNuGet {
|
||||||
|
pname = "fsharp-analyzers";
|
||||||
|
version = "0.26.0";
|
||||||
|
sha256 = "0xgv5kvbwfdvcp6s8x7xagbbi4s3mqa4ixni6pazqvyflbgnah7b";
|
||||||
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "FSharp.Core";
|
pname = "FSharp.Core";
|
||||||
version = "4.3.4";
|
version = "4.3.4";
|
||||||
@@ -56,186 +56,81 @@
|
|||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "1d8nkz24vsm0iy2xm8y5ak2q1w1p99dxyz0y26acs6sfk2na0vm6";
|
sha256 = "1d8nkz24vsm0iy2xm8y5ak2q1w1p99dxyz0y26acs6sfk2na0vm6";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Ref";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "0yaaiqq7mi6sclyrb1v0fyncanbx0ifmnnhv9whynqj8439jsdwh";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "1za8lc52m4z54d68wd64c2nhzy05g3gx171k5cdlx73fbymiys9z";
|
sha256 = "1za8lc52m4z54d68wd64c2nhzy05g3gx171k5cdlx73fbymiys9z";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "0dsdgqg7566qximmjfza4x9if3icy4kskq698ddj5apdia88h2mw";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "1zpbmz6z8758gwywzg0bac8kx9x39sxxc9j4a4r2jl74l9ssw4vm";
|
sha256 = "1zpbmz6z8758gwywzg0bac8kx9x39sxxc9j4a4r2jl74l9ssw4vm";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "1gjz379y61ag9whi78qxx09bwkwcznkx2mzypgycibxk61g11da1";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "1i8ydlwjzk7j0mzvn0rpljxfp1h50zwaqalnyvfxai1fwgigzgw5";
|
sha256 = "1i8ydlwjzk7j0mzvn0rpljxfp1h50zwaqalnyvfxai1fwgigzgw5";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "0w3mrs4zdl9mfanl1j81759xwwrzmicsjxn6yfxv5yrxbxzq695n";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "02src68hd3213sd1a2ms1my7i92knfmdxclvv90il9cky2zsq8kw";
|
sha256 = "02src68hd3213sd1a2ms1my7i92knfmdxclvv90il9cky2zsq8kw";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "0a9aljr4fy4haq6ndz2y723liv5hbfpss1rn45s88nmgcp27m15m";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.win-x64";
|
|
||||||
version = "6.0.26";
|
|
||||||
sha256 = "1gxlmfdkfzmhw9pac5jiv674nn6i1zymcp2hj81irjwhhjk01mf5";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.win-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "01kzndyqmsvcq49i2jrv7ymfp0l71yxfylv1cy3nhkdbprqz8ipx";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.Build.Tasks.Git";
|
|
||||||
version = "8.0.0";
|
|
||||||
sha256 = "0055f69q3hbagqp8gl3nk0vfn4qyqyxsxyy7pd0g7wm3z28byzmx";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.CodeCoverage";
|
pname = "Microsoft.CodeCoverage";
|
||||||
version = "17.9.0";
|
version = "17.10.0";
|
||||||
sha256 = "1gljgi69k0fz8vy8bn6xlyxabj6q4vls2zza9wz7ng6ix3irm89r";
|
sha256 = "0s0v7jmrq85n356xv7zixvwa4z94fszjcr5vll8x4im1a2lp00f9";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NET.Test.Sdk";
|
pname = "Microsoft.NET.Test.Sdk";
|
||||||
version = "17.9.0";
|
version = "17.10.0";
|
||||||
sha256 = "1lls1fly2gr1n9n1xyl9k33l2v4pwfmylyzkq8v4v5ldnwkl1zdb";
|
sha256 = "13g8fwl09li8fc71nk13dgkb7gahd4qhamyg2xby7am63nlchhdf";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "19y6c6v20bgf7x7rrh4rx9y7s5fy8vp5m4j9b6gi1wp4rpb5mza4";
|
sha256 = "19y6c6v20bgf7x7rrh4rx9y7s5fy8vp5m4j9b6gi1wp4rpb5mza4";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "0dhpdlcdz7adcfh9w01fc867051m35fqaxnvj3fqvqhgcm2n3143";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "0p7hhidaa3mnyiwnsijwy8578v843x8hh99255s69qwwyld6falv";
|
sha256 = "0p7hhidaa3mnyiwnsijwy8578v843x8hh99255s69qwwyld6falv";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "1aw6mc7zcmzs1grxz2wa9cw9kfj8pz7zpj417xnp1a9n4ix1bxgr";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "1mq11xsv9g1vsasp6k80y7xlvwi9hrpk5dgm773fvy8538s01gfv";
|
sha256 = "1mq11xsv9g1vsasp6k80y7xlvwi9hrpk5dgm773fvy8538s01gfv";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "1dzg3prng9zfdzz7gcgywjdbwzhwm85j89z0jahynxx4q2dra4b9";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "1chac9b4424ihrrnlzvc7qz6j4ymfjyv4kzyazzzw19yhymdkh2s";
|
sha256 = "1chac9b4424ihrrnlzvc7qz6j4ymfjyv4kzyazzzw19yhymdkh2s";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "010f8wn15s2kv7yyzgys3pv9i1mxw20hpv1ig2zhybjxs8lpj8jj";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.win-x64";
|
|
||||||
version = "6.0.26";
|
|
||||||
sha256 = "0i7g9fsqjnbh9rc6807m57r2idg5pkcw6xjfwhnxkcpgqm96258v";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.win-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "1ssj1cyam3nfidm8q82kvh4i3fzm2lzb3bxw6ck09hwhvwh909z4";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Ref";
|
pname = "Microsoft.NETCore.App.Ref";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "12gb52dhg5h9hgnyqh1zgj2w46paxv2pfh33pphl9ajhrdr7hlsb";
|
sha256 = "12gb52dhg5h9hgnyqh1zgj2w46paxv2pfh33pphl9ajhrdr7hlsb";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Ref";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "02r4jg4ha0qksix9v6s3cpmvavmz54gkawkxy9bvknw5ynxhhl1l";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "164hfrwqz5dxcbb441lridk4mzcqmarb0b7ckgvqhsvpawyjw88v";
|
sha256 = "164hfrwqz5dxcbb441lridk4mzcqmarb0b7ckgvqhsvpawyjw88v";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "0353whnjgz3sqhzsfrviad3a3db4pk7hl7m4wwppv5mqdg9i9ri5";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "0islayddpnflviqpbq4djc4f3v9nhsa2y76k5x6il3csq5vdw2hq";
|
sha256 = "0islayddpnflviqpbq4djc4f3v9nhsa2y76k5x6il3csq5vdw2hq";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "1g5b30f4l8a1zjjr3b8pk9mcqxkxqwa86362f84646xaj4iw3a4d";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "1acn5zw1pxzmcg3c0pbf9hal36fbdh9mvbsiwra7simrk7hzqpdc";
|
sha256 = "1acn5zw1pxzmcg3c0pbf9hal36fbdh9mvbsiwra7simrk7hzqpdc";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "0cdrpdaq5sl3602anfx1p0z0ncx2sjjvl6mgsd6y38g47n7f95jc";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
||||||
version = "6.0.26";
|
version = "6.0.26";
|
||||||
sha256 = "00f9l9dkdz0zv5csaw8fkm6s8ckrj5n9k3ygz12daa22l3bcn6ii";
|
sha256 = "00f9l9dkdz0zv5csaw8fkm6s8ckrj5n9k3ygz12daa22l3bcn6ii";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "1fk1flqp6ji0l4c2gvh83ykndpx7a2nkkgrgkgql3c75j1k2v1s9";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.win-x64";
|
|
||||||
version = "6.0.26";
|
|
||||||
sha256 = "0i2p356phfc5y6qnr3vyrzjfi1mrbwfb6g85k4q37bbyxjfp7zl9";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.win-x64";
|
|
||||||
version = "8.0.1";
|
|
||||||
sha256 = "198576cdkl72xs29zznff9ls763p8pfr0zji7b74dqxd5ga0s3bd";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.NETCore.Platforms";
|
pname = "Microsoft.NETCore.Platforms";
|
||||||
version = "1.1.0";
|
version = "1.1.0";
|
||||||
@@ -256,25 +151,15 @@
|
|||||||
version = "1.1.3";
|
version = "1.1.3";
|
||||||
sha256 = "05smkcyxir59rgrmp7d6327vvrlacdgldfxhmyr1azclvga1zfsq";
|
sha256 = "05smkcyxir59rgrmp7d6327vvrlacdgldfxhmyr1azclvga1zfsq";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.SourceLink.Common";
|
|
||||||
version = "8.0.0";
|
|
||||||
sha256 = "0xrr8yd34ij7dqnyddkp2awfmf9qn3c89xmw2f3npaa4wnajmx81";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.SourceLink.GitHub";
|
|
||||||
version = "8.0.0";
|
|
||||||
sha256 = "1gdx7n45wwia3yvang3ls92sk3wrymqcx9p349j8wba2lyjf9m44";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.TestPlatform.ObjectModel";
|
pname = "Microsoft.TestPlatform.ObjectModel";
|
||||||
version = "17.9.0";
|
version = "17.10.0";
|
||||||
sha256 = "1kgsl9w9fganbm9wvlkqgk0ag9hfi58z88rkfybc6kvg78bx89ca";
|
sha256 = "07j69cw8r39533w4p39mnj00kahazz38760in3jfc45kmlcdb26x";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Microsoft.TestPlatform.TestHost";
|
pname = "Microsoft.TestPlatform.TestHost";
|
||||||
version = "17.9.0";
|
version = "17.10.0";
|
||||||
sha256 = "19ffh31a1jxzn8j69m1vnk5hyfz3dbxmflq77b8x82zybiilh5nl";
|
sha256 = "1bl471s7fx9jycr0cc8rylwf34mrvlg9qn1an6l86nisavfcyb7v";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Myriad.Core";
|
pname = "Myriad.Core";
|
||||||
@@ -288,8 +173,8 @@
|
|||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "Nerdbank.GitVersioning";
|
pname = "Nerdbank.GitVersioning";
|
||||||
version = "3.6.133";
|
version = "3.6.139";
|
||||||
sha256 = "1cdw8krvsnx0n34f7fm5hiiy7bs6h3asvncqcikc0g46l50w2j80";
|
sha256 = "0npcryhq3r0c2zi940jk39h13mzc4hyg7z8gm6jdmxi1aqv1vh8c";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NETStandard.Library";
|
pname = "NETStandard.Library";
|
||||||
@@ -308,33 +193,33 @@
|
|||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NuGet.Common";
|
pname = "NuGet.Common";
|
||||||
version = "6.9.1";
|
version = "6.10.0";
|
||||||
sha256 = "0ic3d46r9v05pkczpmskw86yzixm6iwshbw0ya8i2957nhhlymw8";
|
sha256 = "0nizrnilmlcqbm945293h8q3wfqfchb4xi8g50x4kjn0rbpd1kbh";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NuGet.Configuration";
|
pname = "NuGet.Configuration";
|
||||||
version = "6.9.1";
|
version = "6.10.0";
|
||||||
sha256 = "07z4qgbibpg59j2r05ifnqdyqf2xinm33rx7gjyr1f73kzg01m33";
|
sha256 = "1aqaknaawnqx4mnvx9qw73wvj48jjzv0d78dzwl7m9zjlrl9myhz";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NuGet.Frameworks";
|
pname = "NuGet.Frameworks";
|
||||||
version = "6.9.1";
|
version = "6.10.0";
|
||||||
sha256 = "0s3az3ac53icjnmb14hfjcmkvzscvrkm62jgqf48yvsbysyhqm5s";
|
sha256 = "0hrd8y31zx9a0wps49czw0qgbrakb49zn3abfgylc9xrq990zkqk";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NuGet.Packaging";
|
pname = "NuGet.Packaging";
|
||||||
version = "6.9.1";
|
version = "6.10.0";
|
||||||
sha256 = "0w0arkmzg3qh1brq4vm10zrsjm7nw706ld4y5kqcmvjpd16f4b4y";
|
sha256 = "18s53cvrf51lihmaqqdf48p2qi6ky1l48jv0hvbp76cxwdg7rba4";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NuGet.Protocol";
|
pname = "NuGet.Protocol";
|
||||||
version = "6.7.0";
|
version = "6.10.0";
|
||||||
sha256 = "1v5ibnq2mp801vw68zyj169hkj3xm7h55824i33n1jxxj2vs3vbk";
|
sha256 = "0hmv4q0ks9i34mfgpb13l01la9v3jjllfh1qd3aqv105xrqrdxac";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NuGet.Versioning";
|
pname = "NuGet.Versioning";
|
||||||
version = "6.9.1";
|
version = "6.10.0";
|
||||||
sha256 = "0xrs82dydy9cgxf0qypr01wawwnq1nf6fc7rwisb4y5v4r259fdm";
|
sha256 = "1x19njx4x0sw9fz8y5fibi15xfsrw5avir0cx0599yd7p3ykik5g";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "NUnit";
|
pname = "NUnit";
|
||||||
@@ -433,12 +318,12 @@
|
|||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "System.Text.Encodings.Web";
|
pname = "System.Text.Encodings.Web";
|
||||||
version = "6.0.0";
|
version = "7.0.0";
|
||||||
sha256 = "06n9ql3fmhpjl32g3492sj181zjml5dlcc5l76xq2h38c4f87sai";
|
sha256 = "1151hbyrcf8kyg1jz8k9awpbic98lwz9x129rg7zk1wrs6vjlpxl";
|
||||||
})
|
})
|
||||||
(fetchNuGet {
|
(fetchNuGet {
|
||||||
pname = "System.Text.Json";
|
pname = "System.Text.Json";
|
||||||
version = "6.0.0";
|
version = "7.0.3";
|
||||||
sha256 = "1si2my1g0q0qv1hiqnji4xh9wd05qavxnzj9dwgs23iqvgjky0gl";
|
sha256 = "0zjrnc9lshagm6kdb9bdh45dmlnkpwcpyssa896sda93ngbmj8k9";
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
|
@@ -1,73 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This file was adapted from
|
|
||||||
# https://github.com/NixOS/nixpkgs/blob/b981d811453ab84fb3ea593a9b33b960f1ab9147/pkgs/build-support/dotnet/build-dotnet-module/default.nix#L173
|
|
||||||
set -euo pipefail
|
|
||||||
export PATH="@binPath@"
|
|
||||||
for arg in "$@"; do
|
|
||||||
case "$arg" in
|
|
||||||
--keep-sources|-k)
|
|
||||||
keepSources=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--help|-h)
|
|
||||||
echo "usage: $0 [--keep-sources] [--help] <output path>"
|
|
||||||
echo " <output path> The path to write the lockfile to. A temporary file is used if this is not set"
|
|
||||||
echo " --keep-sources Don't remove temporary directories upon exit, useful for debugging"
|
|
||||||
echo " --help Show this help message"
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
tmp=$(mktemp -td "@pname@-tmp-XXXXXX")
|
|
||||||
export tmp
|
|
||||||
HOME=$tmp/home
|
|
||||||
exitTrap() {
|
|
||||||
test -n "${ranTrap-}" && return
|
|
||||||
ranTrap=1
|
|
||||||
if test -n "${keepSources-}"; then
|
|
||||||
echo -e "Path to the source: $tmp/src\nPath to the fake home: $tmp/home"
|
|
||||||
else
|
|
||||||
rm -rf "$tmp"
|
|
||||||
fi
|
|
||||||
# Since mktemp is used this will be empty if the script didnt succesfully complete
|
|
||||||
if ! test -s "$depsFile"; then
|
|
||||||
rm -rf "$depsFile"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
trap exitTrap EXIT INT TERM
|
|
||||||
dotnetRestore() {
|
|
||||||
local -r project="${1-}"
|
|
||||||
local -r rid="$2"
|
|
||||||
dotnet restore "${project-}" \
|
|
||||||
-p:ContinuousIntegrationBuild=true \
|
|
||||||
-p:Deterministic=true \
|
|
||||||
--packages "$tmp/nuget_pkgs" \
|
|
||||||
--runtime "$rid" \
|
|
||||||
--no-cache \
|
|
||||||
--force
|
|
||||||
}
|
|
||||||
declare -a projectFiles=( @projectFiles@ )
|
|
||||||
declare -a testProjectFiles=( @testProjectFiles@ )
|
|
||||||
export DOTNET_NOLOGO=1
|
|
||||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1
|
|
||||||
depsFile=$(realpath "${1:-$(mktemp -t "@pname@-deps-XXXXXX.nix")}")
|
|
||||||
mkdir -p "$tmp/nuget_pkgs"
|
|
||||||
storeSrc="@storeSrc@"
|
|
||||||
src="$tmp/src"
|
|
||||||
cp -rT "$storeSrc" "$src"
|
|
||||||
chmod -R +w "$src"
|
|
||||||
cd "$src"
|
|
||||||
echo "Restoring project..."
|
|
||||||
rids=("@rids@")
|
|
||||||
for rid in "${rids[@]}"; do
|
|
||||||
(( ${#projectFiles[@]} == 0 )) && dotnetRestore "" "$rid"
|
|
||||||
for project in "${projectFiles[@]-}" "${testProjectFiles[@]-}"; do
|
|
||||||
dotnetRestore "$project" "$rid"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
echo "Successfully restored project"
|
|
||||||
echo "Writing lockfile..."
|
|
||||||
echo -e "# This file was automatically generated by passthru.fetch-deps.\n# Please don't edit it manually, your changes might get overwritten!\n" > "$depsFile"
|
|
||||||
nuget-to-nix "$tmp/nuget_pkgs" "@packages@" >> "$depsFile"
|
|
||||||
echo "Successfully wrote lockfile to $depsFile"
|
|
Reference in New Issue
Block a user