mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-05 12:08:46 +00:00
Compare commits
65 Commits
WoofWare.M
...
du-parser
Author | SHA1 | Date | |
---|---|---|---|
|
f686109331 | ||
|
7b2c3d2168 | ||
|
3ed8d4db00 | ||
|
75ce8c1f64 | ||
|
01714aeba0 | ||
|
2f266b052d | ||
|
d3d50cae7c | ||
|
573d410416 | ||
|
a82ece0f6c | ||
|
51991cab74 | ||
|
55a3876610 | ||
|
c14f89f807 | ||
|
54e3f17d9c | ||
|
4013271254 | ||
|
aa2ef830c3 | ||
|
4e62a154c0 | ||
|
751e43eec4 | ||
|
fccc981045 | ||
|
f8a1505b99 | ||
|
eb25b9ccb8 | ||
|
325f8634a4 | ||
|
34587b8dea | ||
|
3e5d663544 | ||
|
963a097360 | ||
|
67eb89cfc0 | ||
|
0c5ddf9df7 | ||
|
8535481e0d | ||
|
df6079e763 | ||
|
4befdb93e5 | ||
|
17da7317e8 | ||
|
fa022b75ea | ||
|
bb88f80c85 | ||
|
71f26930c6 | ||
|
680728a06e | ||
|
cdc6f2d511 | ||
|
3be487c328 | ||
|
a5f4d169ca | ||
|
ce634efff2 | ||
|
1529dd1fb2 | ||
|
59558b0766 | ||
|
8602894efc | ||
|
51d349b365 | ||
|
120df84bbf | ||
|
603f875a12 | ||
|
2df41555de | ||
|
49e31e52b5 | ||
|
277a186fda | ||
|
129687ec1c | ||
|
c7fea55e28 | ||
|
ded7b32771 | ||
|
b272f8b645 | ||
|
b8d60aec90 | ||
|
0e3510e1e5 | ||
|
8a1edd90d5 | ||
|
74fdd7c0a9 | ||
|
23f55814f9 | ||
|
15c04bb373 | ||
|
a860a93f9c | ||
|
b056af348e | ||
|
b44c8db6e9 | ||
|
7d6a2cea01 | ||
|
d779a602f4 | ||
|
23cd5272fb | ||
|
93538ee6b4 | ||
|
8a29c2f444 |
@@ -3,13 +3,13 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"fantomas": {
|
||||
"version": "6.3.16",
|
||||
"version": "7.0.1",
|
||||
"commands": [
|
||||
"fantomas"
|
||||
]
|
||||
},
|
||||
"fsharp-analyzers": {
|
||||
"version": "0.28.0",
|
||||
"version": "0.30.0",
|
||||
"commands": [
|
||||
"fsharp-analyzers"
|
||||
]
|
||||
|
98
.github/workflows/dotnet.yaml
vendored
98
.github/workflows/dotnet.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -142,7 +142,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -198,27 +198,40 @@ jobs:
|
||||
# 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
|
||||
|
||||
github-release-plugin-dry-run:
|
||||
needs: [nuget-pack]
|
||||
github-release-dry-run:
|
||||
strategy:
|
||||
matrix:
|
||||
artifact:
|
||||
- nuget-package-plugin
|
||||
- nuget-package-attribute
|
||||
runs-on: ubuntu-latest
|
||||
needs: [nuget-pack]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download NuGet artifact (plugin)
|
||||
- name: Download NuGet artifact
|
||||
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
|
||||
name: ${{ matrix.artifact }}
|
||||
- name: Compute package path
|
||||
id: compute-path
|
||||
run: |
|
||||
find . -maxdepth 1 -type f -name 'WoofWare.Myriad.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
|
||||
- name: Compute tag name
|
||||
id: compute-tag
|
||||
env:
|
||||
DRY_RUN: 1
|
||||
GITHUB_TOKEN: mock-token
|
||||
run: sh .github/workflows/tag.sh
|
||||
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
|
||||
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
|
||||
- name: Tag and release
|
||||
uses: G-Research/common-actions/github-release@19d7281a0f9f83e13c78f99a610dbc80fc59ba3b
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
target-commitish: ${{ github.sha }}
|
||||
tag: ${{ steps.compute-tag.outputs.output }}
|
||||
binary-contents: ${{ steps.compute-path.outputs.output }}
|
||||
dry-run: true
|
||||
|
||||
all-required-checks-complete:
|
||||
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]
|
||||
needs: [check-dotnet-format, check-nix-format, check-accurate-generations, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack, github-release-dry-run]
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -241,7 +254,7 @@ jobs:
|
||||
name: nuget-package-attribute
|
||||
path: packed
|
||||
- name: Attest Build Provenance
|
||||
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # v2.1.0
|
||||
uses: actions/attest-build-provenance@c074443f1aee8d4aeeae555aebba3282517141b2 # v2.2.3
|
||||
with:
|
||||
subject-path: "packed/*.nupkg"
|
||||
|
||||
@@ -260,7 +273,7 @@ jobs:
|
||||
name: nuget-package-plugin
|
||||
path: packed
|
||||
- name: Attest Build Provenance
|
||||
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # v2.1.0
|
||||
uses: actions/attest-build-provenance@c074443f1aee8d4aeeae555aebba3282517141b2 # v2.2.3
|
||||
with:
|
||||
subject-path: "packed/*.nupkg"
|
||||
|
||||
@@ -276,7 +289,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -309,7 +322,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
extra_nix_config: |
|
||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -330,7 +343,12 @@ jobs:
|
||||
nupkg-dir: packed/
|
||||
dotnet: ${{ steps.dotnet-identify.outputs.dotnet }}
|
||||
|
||||
github-release-plugin:
|
||||
github-release:
|
||||
strategy:
|
||||
matrix:
|
||||
artifact:
|
||||
- nuget-package-attribute
|
||||
- nuget-package-plugin
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||
needs: [all-required-checks-complete]
|
||||
@@ -339,15 +357,23 @@ jobs:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download NuGet artifact (plugin)
|
||||
- name: Download NuGet artifact
|
||||
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
|
||||
name: ${{ matrix.artifact }}
|
||||
- name: Compute package path
|
||||
id: compute-path
|
||||
run: |
|
||||
find . -maxdepth 1 -type f -name 'WoofWare.Myriad.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
|
||||
- name: Compute tag name
|
||||
id: compute-tag
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: sh .github/workflows/tag.sh
|
||||
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
|
||||
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
|
||||
- name: Tag and release
|
||||
uses: G-Research/common-actions/github-release@19d7281a0f9f83e13c78f99a610dbc80fc59ba3b
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
target-commitish: ${{ github.sha }}
|
||||
tag: ${{ steps.compute-tag.outputs.output }}
|
||||
binary-contents: ${{ steps.compute-path.outputs.output }}
|
||||
|
10
.github/workflows/flake_update.yaml
vendored
10
.github/workflows/flake_update.yaml
vendored
@@ -21,20 +21,20 @@ jobs:
|
||||
- name: Update Nix flake
|
||||
run: 'nix flake update'
|
||||
|
||||
- name: Build passthru
|
||||
run: 'nix build ".#default.passthru.fetch-deps"'
|
||||
- name: Build fetch-deps
|
||||
run: 'nix build ".#default.fetch-deps"'
|
||||
|
||||
- name: Run passthru
|
||||
- name: Run fetch-deps
|
||||
run: |
|
||||
set -o pipefail
|
||||
./result nix/deps.nix
|
||||
./result nix/deps.json
|
||||
|
||||
- name: Format
|
||||
run: 'nix develop --command alejandra .'
|
||||
|
||||
- name: Create token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
# https://github.com/actions/create-github-app-token/issues/136
|
||||
app-id: ${{ secrets.APP_ID }}
|
||||
|
120
.github/workflows/tag.sh
vendored
120
.github/workflows/tag.sh
vendored
@@ -1,120 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
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
|
||||
TAG=$(find . -maxdepth 1 -type f -name 'WoofWare.Myriad.Plugins.*.nupkg' -exec sh -c 'basename "$1" .nupkg' shell {} \; | grep -v Attributes)
|
||||
|
||||
case "$TAG" in
|
||||
*"
|
||||
"*)
|
||||
echo "Error: TAG contains a newline; multiple plugins found."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# target_commitish empty indicates the repo default branch
|
||||
curl_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
|
@@ -235,3 +235,9 @@ type FlagsIntoPositionalArgs' =
|
||||
[<PositionalArgs false>]
|
||||
DontGrabEverything : string list
|
||||
}
|
||||
|
||||
[<ArgParser true>]
|
||||
type PassThru =
|
||||
{
|
||||
A : ParentRecordChildPos
|
||||
}
|
||||
|
35
ConsumePlugin/ArgsWithUnions.fs
Normal file
35
ConsumePlugin/ArgsWithUnions.fs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace ConsumePlugin.ArgsWithUnions
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
type BasicNoPositionals =
|
||||
{
|
||||
Foo : int
|
||||
Bar : string
|
||||
Baz : bool
|
||||
Rest : int list
|
||||
}
|
||||
|
||||
type UsernamePasswordAuth =
|
||||
{
|
||||
Username : string
|
||||
Password : string
|
||||
}
|
||||
|
||||
type TokenAuth =
|
||||
{
|
||||
Token : string
|
||||
}
|
||||
|
||||
type AuthOptions =
|
||||
| UsernamePassword of UsernamePasswordAuth
|
||||
| Token of TokenAuth
|
||||
|
||||
[<ArgParser>]
|
||||
type DoTheThing =
|
||||
{
|
||||
Basics : BasicNoPositionals
|
||||
Auth : AuthOptions
|
||||
}
|
@@ -12,6 +12,7 @@
|
||||
<ItemGroup>
|
||||
<None Include="myriad.toml"/>
|
||||
<Compile Include="AssemblyInfo.fs" />
|
||||
<!--
|
||||
<Compile Include="RecordFile.fs"/>
|
||||
<Compile Include="GeneratedRecord.fs">
|
||||
<MyriadFile>RecordFile.fs</MyriadFile>
|
||||
@@ -66,10 +67,16 @@
|
||||
<Compile Include="ListCata.fs">
|
||||
<MyriadFile>List.fs</MyriadFile>
|
||||
</Compile>
|
||||
-->
|
||||
<Compile Include="Args.fs" />
|
||||
<Compile Include="GeneratedArgs.fs">
|
||||
<MyriadFile>Args.fs</MyriadFile>
|
||||
</Compile>
|
||||
<Compile Include="ArgsWithUnions.fs" />
|
||||
<Compile Include="GeneratedArgsWithUnions.fs">
|
||||
<MyriadFile>ArgsWithUnions.fs</MyriadFile>
|
||||
</Compile>
|
||||
<!--
|
||||
<None Include="swagger-gitea.json" />
|
||||
<Compile Include="GeneratedSwaggerGitea.fs">
|
||||
<MyriadFile>swagger-gitea.json</MyriadFile>
|
||||
@@ -81,6 +88,7 @@
|
||||
<Compile Include="Generated2SwaggerGitea.fs">
|
||||
<MyriadFile>GeneratedSwaggerGitea.fs</MyriadFile>
|
||||
</Compile>
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -26769,8 +26769,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"admin/cron/{task}"
|
||||
.Replace ("{task}", task.ToString () |> System.Uri.EscapeDataString),
|
||||
"admin/cron/{task}".Replace ("{task}", task.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -26902,8 +26901,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"admin/hooks/{id}"
|
||||
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
"admin/hooks/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -26945,8 +26943,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"admin/hooks/{id}"
|
||||
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
"admin/hooks/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -27584,8 +27581,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"amdin/hooks/{id}"
|
||||
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
"amdin/hooks/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -28008,8 +28004,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"org/{org}/repos"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
"org/{org}/repos".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -28292,8 +28287,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
("orgs/{org}/hooks"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
("orgs/{org}/hooks".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
+ (if "orgs/{org}/hooks".IndexOf (char 63) >= 0 then
|
||||
"&"
|
||||
else
|
||||
@@ -28345,8 +28339,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"orgs/{org}/hooks"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
"orgs/{org}/hooks".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -28538,8 +28531,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
("orgs/{org}/labels"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
("orgs/{org}/labels".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
+ (if "orgs/{org}/labels".IndexOf (char 63) >= 0 then
|
||||
"&"
|
||||
else
|
||||
@@ -28591,8 +28583,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"orgs/{org}/labels"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
"orgs/{org}/labels".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -28784,8 +28775,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
("orgs/{org}/members"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
("orgs/{org}/members".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
+ (if "orgs/{org}/members".IndexOf (char 63) >= 0 then
|
||||
"&"
|
||||
else
|
||||
@@ -29086,8 +29076,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
("orgs/{org}/repos"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
("orgs/{org}/repos".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
+ (if "orgs/{org}/repos".IndexOf (char 63) >= 0 then
|
||||
"&"
|
||||
else
|
||||
@@ -29142,8 +29131,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"orgs/{org}/repos"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
"orgs/{org}/repos".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -29197,8 +29185,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
("orgs/{org}/teams"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
("orgs/{org}/teams".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
|
||||
+ (if "orgs/{org}/teams".IndexOf (char 63) >= 0 then
|
||||
"&"
|
||||
else
|
||||
@@ -29250,8 +29237,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"orgs/{org}/teams"
|
||||
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
"orgs/{org}/teams".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -39381,8 +39367,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"repositories/{id}"
|
||||
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
"repositories/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
@@ -39745,8 +39730,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
("teams/{id}/members"
|
||||
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
|
||||
("teams/{id}/members".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
|
||||
+ (if "teams/{id}/members".IndexOf (char 63) >= 0 then
|
||||
"&"
|
||||
else
|
||||
@@ -39918,8 +39902,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
("teams/{id}/repos"
|
||||
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
|
||||
("teams/{id}/repos".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
|
||||
+ (if "teams/{id}/repos".IndexOf (char 63) >= 0 then
|
||||
"&"
|
||||
else
|
||||
@@ -40807,8 +40790,7 @@ module Gitea =
|
||||
System.Uri ("/api/v1/", System.UriKind.Relative)
|
||||
),
|
||||
System.Uri (
|
||||
"user/gpg_keys/{id}"
|
||||
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
"user/gpg_keys/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
686
ConsumePlugin/GeneratedArgsWithUnions.fs
Normal file
686
ConsumePlugin/GeneratedArgsWithUnions.fs
Normal file
@@ -0,0 +1,686 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// This code was generated by myriad.
|
||||
// Changes to this file will be lost when the code is regenerated.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ArgParserHelpers
|
||||
|
||||
/// Helper types for arg parsing
|
||||
module internal ArgParseHelpers_ConsumePlugin_ArgsWithUnions =
|
||||
open System
|
||||
open System.IO
|
||||
open WoofWare.Myriad.Plugins
|
||||
open ConsumePlugin.ArgsWithUnions
|
||||
|
||||
/// A partially-parsed BasicNoPositionals.
|
||||
type internal BasicNoPositionals_InProgress =
|
||||
{
|
||||
mutable Bar : string option
|
||||
mutable Baz : bool option
|
||||
mutable Foo : int option
|
||||
mutable Rest : ResizeArray<int>
|
||||
}
|
||||
|
||||
/// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args.
|
||||
member this.Assemble_
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(positionals : Choice<string * int, string * int> list)
|
||||
: Result<BasicNoPositionals * string option, string list>
|
||||
=
|
||||
let errors = ResizeArray<string> ()
|
||||
let positionalConsumers = ResizeArray<string> ()
|
||||
let outOfPlacePositionals : ResizeArray<string> = ResizeArray ()
|
||||
|
||||
let arg0 : int =
|
||||
match this.Foo with
|
||||
| Some result -> result
|
||||
| None ->
|
||||
errors.Add (sprintf "Required argument '--%s' received no value" "foo")
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
let arg1 : string =
|
||||
match this.Bar with
|
||||
| Some result -> result
|
||||
| None ->
|
||||
errors.Add (sprintf "Required argument '--%s' received no value" "bar")
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
let arg2 : bool =
|
||||
match this.Baz with
|
||||
| Some result -> result
|
||||
| None ->
|
||||
errors.Add (sprintf "Required argument '--%s' received no value" "baz")
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
let arg3 : int list = this.Rest |> Seq.toList
|
||||
|
||||
if positionalConsumers.Count <= 1 then
|
||||
if outOfPlacePositionals.Count > 0 then
|
||||
outOfPlacePositionals
|
||||
|> String.concat " "
|
||||
|> (fun x ->
|
||||
if 0 = outOfPlacePositionals.Count then
|
||||
"Unmatched args which look like they are meant to be flags. " + x
|
||||
else
|
||||
sprintf
|
||||
"Unmatched args which look like they are meant to be flags. If you intended them as positional args, explicitly pass them with the `%s=` syntax, or place them after a trailing `--`. %s"
|
||||
positionalConsumers.[0]
|
||||
x
|
||||
)
|
||||
|> errors.Add
|
||||
else
|
||||
()
|
||||
|
||||
if errors.Count = 0 then
|
||||
Ok (
|
||||
{
|
||||
Foo = arg0
|
||||
Bar = arg1
|
||||
Baz = arg2
|
||||
Rest = arg3
|
||||
},
|
||||
Seq.tryExactlyOne positionalConsumers
|
||||
)
|
||||
else
|
||||
errors |> Seq.toList |> Error
|
||||
else
|
||||
("Multiple parsers consumed positional args; this is an error in the application, not an error by the user: "
|
||||
+ String.concat ", " positionalConsumers)
|
||||
|> List.singleton
|
||||
|> Error
|
||||
|
||||
static member _Empty () : BasicNoPositionals_InProgress =
|
||||
{
|
||||
Bar = None
|
||||
Baz = None
|
||||
Foo = None
|
||||
Rest = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Processes the key-value pair, returning Error if no key was matched.
|
||||
/// If the key is an arg which can have arity 1, but throws when consuming that arg, we return Error(<the message>).
|
||||
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
||||
member this.ProcessKeyValueSelf_
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
if System.String.Equals (key, sprintf "--%s" "rest", System.StringComparison.OrdinalIgnoreCase) then
|
||||
value |> (fun x -> System.Int32.Parse x) |> (fun x -> x) |> this.Rest.Add
|
||||
() |> Ok
|
||||
else if System.String.Equals (key, sprintf "--%s" "foo", System.StringComparison.OrdinalIgnoreCase) then
|
||||
match this.Foo with
|
||||
| Some x ->
|
||||
sprintf
|
||||
"Argument '%s' was supplied multiple times: %s and %s"
|
||||
(sprintf "--%s" "foo")
|
||||
(x.ToString ())
|
||||
(value.ToString ())
|
||||
|> errors_.Add
|
||||
|
||||
Ok ()
|
||||
| None ->
|
||||
try
|
||||
this.Foo <- value |> (fun x -> System.Int32.Parse x) |> Some
|
||||
Ok ()
|
||||
with _ as exc ->
|
||||
exc.Message |> Some |> Error
|
||||
else if System.String.Equals (key, sprintf "--%s" "baz", System.StringComparison.OrdinalIgnoreCase) then
|
||||
match this.Baz with
|
||||
| Some x ->
|
||||
sprintf
|
||||
"Argument '%s' was supplied multiple times: %s and %s"
|
||||
(sprintf "--%s" "baz")
|
||||
(x.ToString ())
|
||||
(value.ToString ())
|
||||
|> errors_.Add
|
||||
|
||||
Ok ()
|
||||
| None ->
|
||||
try
|
||||
this.Baz <- value |> (fun x -> System.Boolean.Parse x) |> Some
|
||||
Ok ()
|
||||
with _ as exc ->
|
||||
exc.Message |> Some |> Error
|
||||
else if System.String.Equals (key, sprintf "--%s" "bar", System.StringComparison.OrdinalIgnoreCase) then
|
||||
match this.Bar with
|
||||
| Some x ->
|
||||
sprintf
|
||||
"Argument '%s' was supplied multiple times: %s and %s"
|
||||
(sprintf "--%s" "bar")
|
||||
(x.ToString ())
|
||||
(value.ToString ())
|
||||
|> errors_.Add
|
||||
|
||||
Ok ()
|
||||
| None ->
|
||||
try
|
||||
this.Bar <- value |> (fun x -> x) |> Some
|
||||
Ok ()
|
||||
with _ as exc ->
|
||||
exc.Message |> Some |> Error
|
||||
else
|
||||
Error None
|
||||
|
||||
member this.ProcessKeyValue
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
match this.ProcessKeyValueSelf_ argNum_ errors_ key value with
|
||||
| Ok () -> Ok ()
|
||||
| Error None -> Error None
|
||||
| Error (Some errorFromLeaf) -> Error (Some errorFromLeaf)
|
||||
|
||||
/// Returns false if we didn't set a value.
|
||||
member this.SetFlagValue_ (errors_ : ResizeArray<string>) (key : string) : bool =
|
||||
if System.String.Equals (key, sprintf "--%s" "baz", System.StringComparison.OrdinalIgnoreCase) then
|
||||
match this.Baz with
|
||||
| Some _ ->
|
||||
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "baz")
|
||||
|> errors_.Add
|
||||
|
||||
true
|
||||
| None ->
|
||||
this.Baz <- true |> Some
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
/// Compute help text for this parser, optionally noting the given prefix on each argument and indenting each line by this many spaces.
|
||||
static member HelpText_ (prefix : string option) (indent : int) : string = failwith "TODO"
|
||||
|
||||
/// A partially-parsed UsernamePasswordAuth.
|
||||
type internal UsernamePasswordAuth_InProgress =
|
||||
{
|
||||
mutable Password : string option
|
||||
mutable Username : string option
|
||||
}
|
||||
|
||||
/// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args.
|
||||
member this.Assemble_
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(positionals : Choice<string * int, string * int> list)
|
||||
: Result<UsernamePasswordAuth * string option, string list>
|
||||
=
|
||||
let errors = ResizeArray<string> ()
|
||||
let positionalConsumers = ResizeArray<string> ()
|
||||
let outOfPlacePositionals : ResizeArray<string> = ResizeArray ()
|
||||
|
||||
let arg0 : string =
|
||||
match this.Username with
|
||||
| Some result -> result
|
||||
| None ->
|
||||
errors.Add (sprintf "Required argument '--%s' received no value" "username")
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
let arg1 : string =
|
||||
match this.Password with
|
||||
| Some result -> result
|
||||
| None ->
|
||||
errors.Add (sprintf "Required argument '--%s' received no value" "password")
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
if positionalConsumers.Count <= 1 then
|
||||
if outOfPlacePositionals.Count > 0 then
|
||||
outOfPlacePositionals
|
||||
|> String.concat " "
|
||||
|> (fun x ->
|
||||
if 0 = outOfPlacePositionals.Count then
|
||||
"Unmatched args which look like they are meant to be flags. " + x
|
||||
else
|
||||
sprintf
|
||||
"Unmatched args which look like they are meant to be flags. If you intended them as positional args, explicitly pass them with the `%s=` syntax, or place them after a trailing `--`. %s"
|
||||
positionalConsumers.[0]
|
||||
x
|
||||
)
|
||||
|> errors.Add
|
||||
else
|
||||
()
|
||||
|
||||
if errors.Count = 0 then
|
||||
Ok (
|
||||
{
|
||||
Username = arg0
|
||||
Password = arg1
|
||||
},
|
||||
Seq.tryExactlyOne positionalConsumers
|
||||
)
|
||||
else
|
||||
errors |> Seq.toList |> Error
|
||||
else
|
||||
("Multiple parsers consumed positional args; this is an error in the application, not an error by the user: "
|
||||
+ String.concat ", " positionalConsumers)
|
||||
|> List.singleton
|
||||
|> Error
|
||||
|
||||
static member _Empty () : UsernamePasswordAuth_InProgress =
|
||||
{
|
||||
Password = None
|
||||
Username = None
|
||||
}
|
||||
|
||||
/// Processes the key-value pair, returning Error if no key was matched.
|
||||
/// If the key is an arg which can have arity 1, but throws when consuming that arg, we return Error(<the message>).
|
||||
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
||||
member this.ProcessKeyValueSelf_
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
if System.String.Equals (key, sprintf "--%s" "username", System.StringComparison.OrdinalIgnoreCase) then
|
||||
match this.Username with
|
||||
| Some x ->
|
||||
sprintf
|
||||
"Argument '%s' was supplied multiple times: %s and %s"
|
||||
(sprintf "--%s" "username")
|
||||
(x.ToString ())
|
||||
(value.ToString ())
|
||||
|> errors_.Add
|
||||
|
||||
Ok ()
|
||||
| None ->
|
||||
try
|
||||
this.Username <- value |> (fun x -> x) |> Some
|
||||
Ok ()
|
||||
with _ as exc ->
|
||||
exc.Message |> Some |> Error
|
||||
else if
|
||||
System.String.Equals (key, sprintf "--%s" "password", System.StringComparison.OrdinalIgnoreCase)
|
||||
then
|
||||
match this.Password with
|
||||
| Some x ->
|
||||
sprintf
|
||||
"Argument '%s' was supplied multiple times: %s and %s"
|
||||
(sprintf "--%s" "password")
|
||||
(x.ToString ())
|
||||
(value.ToString ())
|
||||
|> errors_.Add
|
||||
|
||||
Ok ()
|
||||
| None ->
|
||||
try
|
||||
this.Password <- value |> (fun x -> x) |> Some
|
||||
Ok ()
|
||||
with _ as exc ->
|
||||
exc.Message |> Some |> Error
|
||||
else
|
||||
Error None
|
||||
|
||||
member this.ProcessKeyValue
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
match this.ProcessKeyValueSelf_ argNum_ errors_ key value with
|
||||
| Ok () -> Ok ()
|
||||
| Error None -> Error None
|
||||
| Error (Some errorFromLeaf) -> Error (Some errorFromLeaf)
|
||||
|
||||
/// Returns false if we didn't set a value.
|
||||
member this.SetFlagValue_ (errors_ : ResizeArray<string>) (key : string) : bool = false
|
||||
/// Compute help text for this parser, optionally noting the given prefix on each argument and indenting each line by this many spaces.
|
||||
static member HelpText_ (prefix : string option) (indent : int) : string = failwith "TODO"
|
||||
|
||||
/// A partially-parsed TokenAuth.
|
||||
type internal TokenAuth_InProgress =
|
||||
{
|
||||
mutable Token : string option
|
||||
}
|
||||
|
||||
/// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args.
|
||||
member this.Assemble_
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(positionals : Choice<string * int, string * int> list)
|
||||
: Result<TokenAuth * string option, string list>
|
||||
=
|
||||
let errors = ResizeArray<string> ()
|
||||
let positionalConsumers = ResizeArray<string> ()
|
||||
let outOfPlacePositionals : ResizeArray<string> = ResizeArray ()
|
||||
|
||||
let arg0 : string =
|
||||
match this.Token with
|
||||
| Some result -> result
|
||||
| None ->
|
||||
errors.Add (sprintf "Required argument '--%s' received no value" "token")
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
if positionalConsumers.Count <= 1 then
|
||||
if outOfPlacePositionals.Count > 0 then
|
||||
outOfPlacePositionals
|
||||
|> String.concat " "
|
||||
|> (fun x ->
|
||||
if 0 = outOfPlacePositionals.Count then
|
||||
"Unmatched args which look like they are meant to be flags. " + x
|
||||
else
|
||||
sprintf
|
||||
"Unmatched args which look like they are meant to be flags. If you intended them as positional args, explicitly pass them with the `%s=` syntax, or place them after a trailing `--`. %s"
|
||||
positionalConsumers.[0]
|
||||
x
|
||||
)
|
||||
|> errors.Add
|
||||
else
|
||||
()
|
||||
|
||||
if errors.Count = 0 then
|
||||
Ok (
|
||||
{
|
||||
Token = arg0
|
||||
},
|
||||
Seq.tryExactlyOne positionalConsumers
|
||||
)
|
||||
else
|
||||
errors |> Seq.toList |> Error
|
||||
else
|
||||
("Multiple parsers consumed positional args; this is an error in the application, not an error by the user: "
|
||||
+ String.concat ", " positionalConsumers)
|
||||
|> List.singleton
|
||||
|> Error
|
||||
|
||||
static member _Empty () : TokenAuth_InProgress =
|
||||
{
|
||||
Token = None
|
||||
}
|
||||
|
||||
/// Processes the key-value pair, returning Error if no key was matched.
|
||||
/// If the key is an arg which can have arity 1, but throws when consuming that arg, we return Error(<the message>).
|
||||
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
||||
member this.ProcessKeyValueSelf_
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
if System.String.Equals (key, sprintf "--%s" "token", System.StringComparison.OrdinalIgnoreCase) then
|
||||
match this.Token with
|
||||
| Some x ->
|
||||
sprintf
|
||||
"Argument '%s' was supplied multiple times: %s and %s"
|
||||
(sprintf "--%s" "token")
|
||||
(x.ToString ())
|
||||
(value.ToString ())
|
||||
|> errors_.Add
|
||||
|
||||
Ok ()
|
||||
| None ->
|
||||
try
|
||||
this.Token <- value |> (fun x -> x) |> Some
|
||||
Ok ()
|
||||
with _ as exc ->
|
||||
exc.Message |> Some |> Error
|
||||
else
|
||||
Error None
|
||||
|
||||
member this.ProcessKeyValue
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
match this.ProcessKeyValueSelf_ argNum_ errors_ key value with
|
||||
| Ok () -> Ok ()
|
||||
| Error None -> Error None
|
||||
| Error (Some errorFromLeaf) -> Error (Some errorFromLeaf)
|
||||
|
||||
/// Returns false if we didn't set a value.
|
||||
member this.SetFlagValue_ (errors_ : ResizeArray<string>) (key : string) : bool = false
|
||||
/// Compute help text for this parser, optionally noting the given prefix on each argument and indenting each line by this many spaces.
|
||||
static member HelpText_ (prefix : string option) (indent : int) : string = failwith "TODO"
|
||||
|
||||
/// A partially-parsed AuthOptions.
|
||||
type internal AuthOptions_InProgress =
|
||||
{
|
||||
Token : TokenAuth_InProgress
|
||||
UsernamePassword : UsernamePasswordAuth_InProgress
|
||||
}
|
||||
|
||||
/// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args.
|
||||
member this.Assemble_
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(positionals : Choice<string * int, string * int> list)
|
||||
: Result<AuthOptions * string option, string list>
|
||||
=
|
||||
failwith "TODO"
|
||||
|
||||
static member _Empty () : AuthOptions_InProgress =
|
||||
{
|
||||
Token = TokenAuth_InProgress._Empty ()
|
||||
UsernamePassword = UsernamePasswordAuth_InProgress._Empty ()
|
||||
}
|
||||
|
||||
/// Compute help text for this parser, optionally noting the given prefix on each argument and indenting each line by this many spaces.
|
||||
static member HelpText_ (prefix : string option) (indent : int) : string = failwith "TODO"
|
||||
|
||||
/// A partially-parsed DoTheThing.
|
||||
type internal DoTheThing_InProgress =
|
||||
{
|
||||
mutable Auth : AuthOptions_InProgress
|
||||
mutable Basics : BasicNoPositionals_InProgress
|
||||
}
|
||||
|
||||
/// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args.
|
||||
member this.Assemble_
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(positionals : Choice<string * int, string * int> list)
|
||||
: Result<DoTheThing * string option, string list>
|
||||
=
|
||||
let errors = ResizeArray<string> ()
|
||||
let positionalConsumers = ResizeArray<string> ()
|
||||
let outOfPlacePositionals : ResizeArray<string> = ResizeArray ()
|
||||
|
||||
let arg0 : BasicNoPositionals =
|
||||
match this.Basics.Assemble_ getEnvironmentVariable positionals with
|
||||
| Ok (result, consumedPositional) ->
|
||||
match consumedPositional with
|
||||
| None -> ()
|
||||
| Some positionalConsumer -> positionalConsumers.Add positionalConsumer
|
||||
|
||||
result
|
||||
| Error err ->
|
||||
errors.AddRange err
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
let arg1 : AuthOptions =
|
||||
match this.Auth.Assemble_ getEnvironmentVariable positionals with
|
||||
| Ok (result, consumedPositional) ->
|
||||
match consumedPositional with
|
||||
| None -> ()
|
||||
| Some positionalConsumer -> positionalConsumers.Add positionalConsumer
|
||||
|
||||
result
|
||||
| Error err ->
|
||||
errors.AddRange err
|
||||
Unchecked.defaultof<_>
|
||||
|
||||
if positionalConsumers.Count <= 1 then
|
||||
if outOfPlacePositionals.Count > 0 then
|
||||
outOfPlacePositionals
|
||||
|> String.concat " "
|
||||
|> (fun x ->
|
||||
if 0 = outOfPlacePositionals.Count then
|
||||
"Unmatched args which look like they are meant to be flags. " + x
|
||||
else
|
||||
sprintf
|
||||
"Unmatched args which look like they are meant to be flags. If you intended them as positional args, explicitly pass them with the `%s=` syntax, or place them after a trailing `--`. %s"
|
||||
positionalConsumers.[0]
|
||||
x
|
||||
)
|
||||
|> errors.Add
|
||||
else
|
||||
()
|
||||
|
||||
if errors.Count = 0 then
|
||||
Ok (
|
||||
{
|
||||
Basics = arg0
|
||||
Auth = arg1
|
||||
},
|
||||
Seq.tryExactlyOne positionalConsumers
|
||||
)
|
||||
else
|
||||
errors |> Seq.toList |> Error
|
||||
else
|
||||
("Multiple parsers consumed positional args; this is an error in the application, not an error by the user: "
|
||||
+ String.concat ", " positionalConsumers)
|
||||
|> List.singleton
|
||||
|> Error
|
||||
|
||||
static member _Empty () : DoTheThing_InProgress =
|
||||
{
|
||||
Basics = BasicNoPositionals_InProgress._Empty ()
|
||||
Auth = AuthOptions_InProgress._Empty ()
|
||||
}
|
||||
|
||||
/// Passes the key-value pair to any child records, returning Error if no key was matched.
|
||||
/// If the key is an arg which can have arity 1, but throws when consuming that arg, we return Error(<the message>).
|
||||
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
||||
member this.ProcessKeyValueRecord_
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
let errors : ResizeArray<string> = ResizeArray ()
|
||||
|
||||
match this.Basics.ProcessKeyValue argNum_ errors_ key value with
|
||||
| Ok () -> Ok ()
|
||||
| Error e -> Error None
|
||||
|
||||
member this.ProcessKeyValue
|
||||
(argNum_ : int)
|
||||
(errors_ : ResizeArray<string>)
|
||||
(key : string)
|
||||
(value : string)
|
||||
: Result<unit, string option>
|
||||
=
|
||||
match this.ProcessKeyValueRecord_ argNum_ errors_ key value with
|
||||
| Ok () -> Ok ()
|
||||
| Error errorFromRecord -> Error errorFromRecord
|
||||
|
||||
/// Returns false if we didn't set a value.
|
||||
member this.SetFlagValue_ (errors_ : ResizeArray<string>) (key : string) : bool = false
|
||||
/// Compute help text for this parser, optionally noting the given prefix on each argument and indenting each line by this many spaces.
|
||||
static member HelpText_ (prefix : string option) (indent : int) : string = failwith "TODO"
|
||||
namespace ConsumePlugin.ArgsWithUnions
|
||||
|
||||
open ArgParserHelpers
|
||||
open System
|
||||
open System.IO
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
/// Methods to parse arguments for the type DoTheThing
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module DoTheThing =
|
||||
type internal ParseState_DoTheThing =
|
||||
/// Ready to consume a key or positional arg
|
||||
| AwaitingKey
|
||||
/// Waiting to receive a value for the key we've already consumed
|
||||
| AwaitingValue of key : string
|
||||
|
||||
let parse' (getEnvironmentVariable : string -> string) (args : string list) : DoTheThing =
|
||||
let inProgress =
|
||||
ArgParseHelpers_ConsumePlugin_ArgsWithUnions.DoTheThing_InProgress._Empty ()
|
||||
|
||||
let positionals : ResizeArray<Choice<string * int, string * int>> = ResizeArray ()
|
||||
let errors_ = ResizeArray ()
|
||||
|
||||
let rec go (argNum_ : int) (state : ParseState_DoTheThing) (args : string list) =
|
||||
match args with
|
||||
| [] ->
|
||||
match state with
|
||||
| ParseState_DoTheThing.AwaitingKey -> ()
|
||||
| ParseState_DoTheThing.AwaitingValue key ->
|
||||
if inProgress.SetFlagValue_ errors_ key then
|
||||
()
|
||||
else
|
||||
sprintf
|
||||
"Trailing argument %s had no value. Use a double-dash to separate positional args from key-value args."
|
||||
key
|
||||
|> errors_.Add
|
||||
| "--" :: rest -> positionals.AddRange (rest |> Seq.map (fun x -> (x, argNum_ + 1)) |> Seq.map Choice2Of2)
|
||||
| arg :: args ->
|
||||
match state with
|
||||
| ParseState_DoTheThing.AwaitingKey ->
|
||||
if arg.StartsWith ("--", System.StringComparison.Ordinal) then
|
||||
if arg = "--help" then
|
||||
"TODO" |> failwithf "Help text requested.\n%s"
|
||||
else
|
||||
let equals = arg.IndexOf (char 61)
|
||||
|
||||
if equals < 0 then
|
||||
go (argNum_ + 1) (ParseState_DoTheThing.AwaitingValue arg) args
|
||||
else
|
||||
let key = arg.[0 .. equals - 1]
|
||||
let value = arg.[equals + 1 ..]
|
||||
|
||||
match inProgress.ProcessKeyValue argNum_ errors_ key value with
|
||||
| Ok () -> go (argNum_ + 1) ParseState_DoTheThing.AwaitingKey args
|
||||
| Error x ->
|
||||
match x with
|
||||
| None ->
|
||||
positionals.Add (Choice1Of2 (arg, argNum_))
|
||||
go (argNum_ + 1) ParseState_DoTheThing.AwaitingKey args
|
||||
| Some msg ->
|
||||
sprintf "%s (at arg %s)" msg arg |> errors_.Add
|
||||
go (argNum_ + 1) ParseState_DoTheThing.AwaitingKey args
|
||||
else
|
||||
(arg, argNum_) |> Choice1Of2 |> positionals.Add
|
||||
go (argNum_ + 1) ParseState_DoTheThing.AwaitingKey args
|
||||
| ParseState_DoTheThing.AwaitingValue key ->
|
||||
match inProgress.ProcessKeyValue argNum_ errors_ key arg with
|
||||
| Ok () -> go argNum_ ParseState_DoTheThing.AwaitingKey args
|
||||
| Error exc ->
|
||||
if inProgress.SetFlagValue_ errors_ key then
|
||||
go argNum_ ParseState_DoTheThing.AwaitingKey (arg :: args)
|
||||
else
|
||||
(key, argNum_) |> Choice1Of2 |> positionals.Add
|
||||
go (argNum_ + 1) ParseState_DoTheThing.AwaitingKey (arg :: args)
|
||||
|
||||
go 0 ParseState_DoTheThing.AwaitingKey args
|
||||
|
||||
if 0 = errors_.Count then
|
||||
()
|
||||
else
|
||||
errors_
|
||||
|> String.concat System.Environment.NewLine
|
||||
|> (fun x -> "Errors during parse!\n" + x)
|
||||
|> failwith
|
||||
|
||||
match inProgress.Assemble_ getEnvironmentVariable (positionals |> Seq.toList) with
|
||||
| Ok (result, posConsumer) ->
|
||||
if positionals.Count > 0 && posConsumer.IsNone then
|
||||
positionals
|
||||
|> Seq.map (fun choiceValue ->
|
||||
match choiceValue with
|
||||
| Choice1Of2 (arg, _) -> arg
|
||||
| Choice2Of2 (arg, _) -> arg
|
||||
)
|
||||
|> String.concat " "
|
||||
|> sprintf "Parse error: The following arguments were not consumed: %s"
|
||||
|> failwith
|
||||
else
|
||||
result
|
||||
| Error e ->
|
||||
e
|
||||
|> String.concat System.Environment.NewLine
|
||||
|> (fun x -> "Errors during parse!\n" + x)
|
||||
|> failwith
|
||||
|
||||
let parse (args : string list) : DoTheThing =
|
||||
parse' System.Environment.GetEnvironmentVariable args
|
@@ -206,3 +206,34 @@ type internal TypeWithInterfaceMock =
|
||||
|
||||
interface System.IDisposable with
|
||||
member this.Dispose () : unit = this.Dispose ()
|
||||
namespace SomeNamespace
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
/// Mock record type for an interface
|
||||
type internal TypeWithPropertiesMock =
|
||||
{
|
||||
/// Implementation of IDisposable.Dispose
|
||||
Dispose : unit -> unit
|
||||
Prop1 : unit -> int
|
||||
Prop2 : unit -> unit Async
|
||||
Mem1 : string option -> string[] Async
|
||||
}
|
||||
|
||||
/// An implementation where every method throws.
|
||||
static member Empty : TypeWithPropertiesMock =
|
||||
{
|
||||
Dispose = (fun () -> ())
|
||||
Prop1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop1"))
|
||||
Prop2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop2"))
|
||||
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
|
||||
}
|
||||
|
||||
interface TypeWithProperties with
|
||||
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
|
||||
member this.Prop1 = this.Prop1 ()
|
||||
member this.Prop2 = this.Prop2 ()
|
||||
|
||||
interface System.IDisposable with
|
||||
member this.Dispose () : unit = this.Dispose ()
|
||||
|
@@ -160,8 +160,7 @@ module PureGymApi =
|
||||
| null -> System.Uri "https://whatnot.com/"
|
||||
| v -> v),
|
||||
System.Uri (
|
||||
"v1/gyms/{gym}"
|
||||
.Replace ("{gym}", gym.ToString () |> System.Uri.EscapeDataString),
|
||||
"v1/gyms/{gym}".Replace ("{gym}", gym.ToString () |> System.Uri.EscapeDataString),
|
||||
System.UriKind.Relative
|
||||
)
|
||||
)
|
||||
|
@@ -48,3 +48,10 @@ type TypeWithInterface =
|
||||
inherit IDisposable
|
||||
abstract Mem1 : string option -> string[] Async
|
||||
abstract Mem2 : unit -> string[] Async
|
||||
|
||||
[<GenerateMock>]
|
||||
type TypeWithProperties =
|
||||
inherit IDisposable
|
||||
abstract Mem1 : string option -> string[] Async
|
||||
abstract Prop1 : int
|
||||
abstract Prop2 : unit Async
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<WarnOn>FS3388,FS3559</WarnOn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.7.112" PrivateAssets="all"/>
|
||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.8.38-alpha" PrivateAssets="all"/>
|
||||
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com"/>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">
|
||||
|
47
Playground/Domain.fs
Normal file
47
Playground/Domain.fs
Normal file
@@ -0,0 +1,47 @@
|
||||
namespace Playground
|
||||
|
||||
open System
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
[<ArgParser>]
|
||||
type SubMode1 =
|
||||
{
|
||||
Info1 : int
|
||||
Info2 : string
|
||||
Rest : string list
|
||||
}
|
||||
|
||||
[<ArgParser>]
|
||||
type SubMode2 =
|
||||
{
|
||||
Info1 : int
|
||||
Info2 : string
|
||||
Rest : int list
|
||||
}
|
||||
|
||||
[<ArgParser>]
|
||||
type Mode1 =
|
||||
{
|
||||
Things : SubMode1
|
||||
Whatnot : int
|
||||
}
|
||||
|
||||
[<ArgParser>]
|
||||
type Mode2 =
|
||||
{
|
||||
Things : SubMode2
|
||||
Whatnot : DateTime
|
||||
}
|
||||
|
||||
[<ArgParser>]
|
||||
type Modes =
|
||||
| Mode1 of Mode1
|
||||
| Mode2 of Mode2
|
||||
|
||||
[<ArgParser>]
|
||||
type Args =
|
||||
{
|
||||
WhatToDo : Modes
|
||||
[<PositionalArgs>]
|
||||
OtherArgs : string list
|
||||
}
|
563
Playground/Library.fs
Normal file
563
Playground/Library.fs
Normal file
@@ -0,0 +1,563 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// This code was generated by myriad.
|
||||
// Changes to this file will be lost when the code is regenerated.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Playground // Assuming a namespace
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open WoofWare.Myriad.Plugins // Assuming attributes are here
|
||||
|
||||
// Assume original type definitions are accessible here
|
||||
// [<ArgParser>] type SubMode1 = { Info1 : int; Info2 : string; Rest : string list }
|
||||
// [<ArgParser>] type SubMode2 = { Info1 : int; Info2 : string; Rest : int list }
|
||||
// [<ArgParser>] type Mode1 = { Things : SubMode1; Whatnot : int }
|
||||
// [<ArgParser>] type Mode2 = { Things : SubMode2; Whatnot : DateTime }
|
||||
// [<ArgParser>] type Modes = | Mode1 of Mode1 | Mode2 of Mode2
|
||||
// [<ArgParser>] type Args = { WhatToDo : Modes; [<PositionalArgs>] OtherArgs : string list }
|
||||
|
||||
|
||||
/// Methods to parse arguments for the type Args
|
||||
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module Args =
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Internal state definitions (Non-Flattened with combined Assemble/Validate)
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/// State representing the parse progress for SubMode1 record
|
||||
type private State_SubMode1 =
|
||||
{
|
||||
mutable Info1 : int option
|
||||
mutable Info2 : string option
|
||||
Rest : ResizeArray<string> // Corresponds to --rest
|
||||
}
|
||||
|
||||
static member Create () =
|
||||
{
|
||||
Info1 = None
|
||||
Info2 = None
|
||||
Rest = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Check completeness and assemble the SubMode1 record from state.
|
||||
member this.Assemble () : Result<SubMode1, string list> =
|
||||
let errors = ResizeArray<string> ()
|
||||
let mutable complete = true
|
||||
|
||||
if this.Info1.IsNone then
|
||||
complete <- false
|
||||
errors.Add ("Argument '--info1' is required.")
|
||||
|
||||
if this.Info2.IsNone then
|
||||
complete <- false
|
||||
errors.Add ("Argument '--info2' is required.")
|
||||
// Rest is list, always 'complete'
|
||||
|
||||
if complete then
|
||||
Ok
|
||||
{
|
||||
Info1 = this.Info1.Value
|
||||
Info2 = this.Info2.Value
|
||||
Rest = this.Rest |> Seq.toList
|
||||
}
|
||||
else
|
||||
Error (errors |> Seq.toList)
|
||||
|
||||
/// State representing the parse progress for SubMode2 record
|
||||
type private State_SubMode2 =
|
||||
{
|
||||
mutable Info1 : int option
|
||||
mutable Info2 : string option
|
||||
Rest : ResizeArray<int> // Corresponds to --rest
|
||||
}
|
||||
|
||||
static member Create () =
|
||||
{
|
||||
Info1 = None
|
||||
Info2 = None
|
||||
Rest = ResizeArray ()
|
||||
}
|
||||
|
||||
/// Check completeness and assemble the SubMode2 record from state.
|
||||
member this.Assemble () : Result<SubMode2, string list> =
|
||||
let errors = ResizeArray<string> ()
|
||||
|
||||
if this.Info1.IsNone then
|
||||
errors.Add ("Argument '--info1' is required.")
|
||||
|
||||
if this.Info2.IsNone then
|
||||
errors.Add ("Argument '--info2' is required.")
|
||||
// Rest is list, always 'complete'
|
||||
|
||||
if errors.Count = 0 then
|
||||
Ok
|
||||
{
|
||||
Info1 = this.Info1.Value
|
||||
Info2 = this.Info2.Value
|
||||
Rest = this.Rest |> Seq.toList
|
||||
}
|
||||
else
|
||||
Error (errors |> Seq.toList)
|
||||
|
||||
|
||||
/// State representing the parse progress for Mode1 record (references SubMode1 state)
|
||||
type private State_Mode1 =
|
||||
{
|
||||
ThingsState : State_SubMode1 // Holds state for the nested record
|
||||
mutable Whatnot : int option
|
||||
}
|
||||
|
||||
static member Create () =
|
||||
{
|
||||
ThingsState = State_SubMode1.Create ()
|
||||
Whatnot = None
|
||||
}
|
||||
|
||||
/// Check completeness and assemble the Mode1 record from state (including nested).
|
||||
member this.Assemble () : Result<Mode1, string list> =
|
||||
let errors = ResizeArray<string> ()
|
||||
|
||||
// Check direct fields
|
||||
if this.Whatnot.IsNone then
|
||||
errors.Add ("Argument '--whatnot' is required for Mode1.")
|
||||
|
||||
// Assemble nested state (which includes its own validation)
|
||||
let thingsResult = this.ThingsState.Assemble ()
|
||||
let mutable thingsValue = None
|
||||
|
||||
match thingsResult with
|
||||
| Ok v -> thingsValue <- Some v
|
||||
| Error nestedErrors -> errors.AddRange (nestedErrors |> List.map (sprintf "Things: %s")) // Add context
|
||||
|
||||
if errors.Count = 0 then
|
||||
Ok
|
||||
{
|
||||
Things = thingsValue.Value
|
||||
Whatnot = this.Whatnot.Value
|
||||
}
|
||||
else
|
||||
Error (errors |> Seq.toList)
|
||||
|
||||
|
||||
/// State representing the parse progress for Mode2 record (references SubMode2 state)
|
||||
type private State_Mode2 =
|
||||
{
|
||||
ThingsState : State_SubMode2 // Holds state for the nested record
|
||||
mutable Whatnot : DateTime option
|
||||
}
|
||||
|
||||
static member Create () =
|
||||
{
|
||||
ThingsState = State_SubMode2.Create ()
|
||||
Whatnot = None
|
||||
}
|
||||
|
||||
/// Check completeness and assemble the Mode2 record from state (including nested).
|
||||
member this.Assemble () : Result<Mode2, string list> =
|
||||
let errors = ResizeArray<string> ()
|
||||
|
||||
// Check direct fields
|
||||
if this.Whatnot.IsNone then
|
||||
errors.Add ("Argument '--whatnot' is required for Mode2.")
|
||||
|
||||
// Assemble nested state (which includes its own validation)
|
||||
let thingsResult = this.ThingsState.Assemble ()
|
||||
let mutable thingsValue = Unchecked.defaultof<_>
|
||||
|
||||
match thingsResult with
|
||||
| Ok v -> thingsValue <- v
|
||||
| Error nestedErrors -> errors.AddRange (nestedErrors |> List.map (sprintf "Things: %s")) // Add context
|
||||
|
||||
if errors.Count = 0 then
|
||||
{
|
||||
Things = thingsValue
|
||||
Whatnot = this.Whatnot.Value
|
||||
}
|
||||
|> Ok
|
||||
else
|
||||
Error (errors |> Seq.toList)
|
||||
|
||||
|
||||
/// State for a single candidate parse path for the Modes DU (Structure unchanged)
|
||||
type private CandidateParseState_Modes =
|
||||
{
|
||||
CaseName : string // "Mode1" or "Mode2"
|
||||
mutable IsViable : bool
|
||||
Errors : ResizeArray<string> // Errors specific to this candidate's path
|
||||
ConsumedArgIndices : System.Collections.Generic.HashSet<int> // Indices consumed *by this candidate*
|
||||
CaseState : obj // Holds either State_Mode1 or State_Mode2
|
||||
}
|
||||
|
||||
static member CreateMode1 () =
|
||||
{
|
||||
CaseName = "Mode1"
|
||||
IsViable = true
|
||||
Errors = ResizeArray ()
|
||||
ConsumedArgIndices = System.Collections.Generic.HashSet ()
|
||||
CaseState = State_Mode1.Create () :> obj
|
||||
}
|
||||
|
||||
static member CreateMode2 () =
|
||||
{
|
||||
CaseName = "Mode2"
|
||||
IsViable = true
|
||||
Errors = ResizeArray ()
|
||||
ConsumedArgIndices = System.Collections.Generic.HashSet ()
|
||||
CaseState = State_Mode2.Create () :> obj
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Main Parser Logic
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
type private ParseState_Args =
|
||||
| AwaitingArg
|
||||
| AwaitingValue of keyIndex : int * key : string
|
||||
|
||||
let parse' (getEnvironmentVariable : string -> string) (args : string list) : Args =
|
||||
let ArgParser_errors = ResizeArray () // Global errors accumulator
|
||||
|
||||
let helpText () =
|
||||
// Help text generation unchanged
|
||||
[
|
||||
(sprintf "%s int32%s%s" (sprintf "--%s" "info1") "" " (for Mode1/Mode2 Things)")
|
||||
(sprintf "%s string%s%s" (sprintf "--%s" "info2") "" " (for Mode1/Mode2 Things)")
|
||||
(sprintf "%s string%s%s" (sprintf "--%s" "rest") " (can be repeated)" " (for Mode1 Things)")
|
||||
(sprintf "%s int32%s%s" (sprintf "--%s" "rest") " (can be repeated)" " (for Mode2 Things)")
|
||||
(sprintf "%s int32%s%s" (sprintf "--%s" "whatnot") "" " (for Mode1)")
|
||||
(sprintf "%s DateTime%s%s" (sprintf "--%s" "whatnot") "" " (for Mode2)")
|
||||
(sprintf "%s string%s%s" (sprintf "--%s" "other-args") " (positional args) (can be repeated)" "")
|
||||
]
|
||||
|> String.concat "\n"
|
||||
|
||||
let arg_OtherArgs : string ResizeArray = ResizeArray ()
|
||||
|
||||
let mutable candidates_WhatToDo : CandidateParseState_Modes list =
|
||||
[
|
||||
CandidateParseState_Modes.CreateMode1 ()
|
||||
CandidateParseState_Modes.CreateMode2 ()
|
||||
]
|
||||
|
||||
let consumedArgIndices_WhatToDo = System.Collections.Generic.HashSet<int> ()
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helper functions for applying args (applyKeyValueToSubModeXState unchanged)
|
||||
//----------------------------------------------------------------------
|
||||
let applyKeyValueToSubMode1State
|
||||
(argIndex : int)
|
||||
(keyIndex : int)
|
||||
(key : string)
|
||||
(value : string)
|
||||
(subState : State_SubMode1)
|
||||
(candidate : CandidateParseState_Modes)
|
||||
: unit
|
||||
=
|
||||
// ... (Implementation identical to previous version) ...
|
||||
if String.Equals (key, "--info1", StringComparison.OrdinalIgnoreCase) then
|
||||
match subState.Info1 with
|
||||
| Some _ ->
|
||||
candidate.Errors.Add (sprintf "Argument '--info1' supplied multiple times (SubMode1)")
|
||||
candidate.IsViable <- false
|
||||
| None ->
|
||||
try
|
||||
subState.Info1 <- Some (Int32.Parse value)
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
with ex ->
|
||||
candidate.Errors.Add (
|
||||
sprintf "Failed to parse '%s' for --info1 (SubMode1): %s" value ex.Message
|
||||
)
|
||||
|
||||
candidate.IsViable <- false
|
||||
elif String.Equals (key, "--info2", StringComparison.OrdinalIgnoreCase) then
|
||||
match subState.Info2 with
|
||||
| Some _ ->
|
||||
candidate.Errors.Add (sprintf "Argument '--info2' supplied multiple times (SubMode1)")
|
||||
candidate.IsViable <- false
|
||||
| None ->
|
||||
subState.Info2 <- Some value
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
elif String.Equals (key, "--rest", StringComparison.OrdinalIgnoreCase) then
|
||||
subState.Rest.Add value
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
else
|
||||
()
|
||||
|
||||
let applyKeyValueToSubMode2State
|
||||
(argIndex : int)
|
||||
(keyIndex : int)
|
||||
(key : string)
|
||||
(value : string)
|
||||
(subState : State_SubMode2)
|
||||
(candidate : CandidateParseState_Modes)
|
||||
: unit
|
||||
=
|
||||
// ... (Implementation identical to previous version) ...
|
||||
if String.Equals (key, "--info1", StringComparison.OrdinalIgnoreCase) then
|
||||
match subState.Info1 with
|
||||
| Some _ ->
|
||||
candidate.Errors.Add (sprintf "Argument '--info1' supplied multiple times (SubMode2)")
|
||||
candidate.IsViable <- false
|
||||
| None ->
|
||||
try
|
||||
subState.Info1 <- Some (Int32.Parse value)
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
with ex ->
|
||||
candidate.Errors.Add (
|
||||
sprintf "Failed to parse '%s' for --info1 (SubMode2): %s" value ex.Message
|
||||
)
|
||||
|
||||
candidate.IsViable <- false
|
||||
elif String.Equals (key, "--info2", StringComparison.OrdinalIgnoreCase) then
|
||||
match subState.Info2 with
|
||||
| Some _ ->
|
||||
candidate.Errors.Add (sprintf "Argument '--info2' supplied multiple times (SubMode2)")
|
||||
candidate.IsViable <- false
|
||||
| None ->
|
||||
subState.Info2 <- Some value
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
elif String.Equals (key, "--rest", StringComparison.OrdinalIgnoreCase) then
|
||||
try
|
||||
subState.Rest.Add (Int32.Parse value)
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
with ex ->
|
||||
candidate.Errors.Add (
|
||||
sprintf "Failed to parse '%s' as int32 for --rest (SubMode2): %s" value ex.Message
|
||||
)
|
||||
|
||||
candidate.IsViable <- false
|
||||
else
|
||||
()
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Routing and Main Application Logic (applyKeyValueToCandidate unchanged)
|
||||
//----------------------------------------------------------------------
|
||||
let applyKeyValueToCandidate
|
||||
(argIndex : int, keyIndex : int, key : string, value : string)
|
||||
(candidate : CandidateParseState_Modes)
|
||||
: unit
|
||||
=
|
||||
// ... (Implementation identical to previous version, calling sub-state helpers) ...
|
||||
if not candidate.IsViable then
|
||||
()
|
||||
else
|
||||
|
||||
match candidate.CaseName with
|
||||
| "Mode1" ->
|
||||
let state = candidate.CaseState :?> State_Mode1
|
||||
|
||||
if String.Equals (key, "--whatnot", StringComparison.OrdinalIgnoreCase) then
|
||||
match state.Whatnot with
|
||||
| Some _ ->
|
||||
candidate.Errors.Add (
|
||||
sprintf "Argument '--whatnot' supplied multiple times for Mode1 candidate"
|
||||
)
|
||||
|
||||
candidate.IsViable <- false
|
||||
| None ->
|
||||
try
|
||||
state.Whatnot <- Some (Int32.Parse value)
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
with ex ->
|
||||
candidate.Errors.Add (
|
||||
sprintf "Failed to parse '%s' as int32 for --whatnot (Mode1): %s" value ex.Message
|
||||
)
|
||||
|
||||
candidate.IsViable <- false
|
||||
elif key = "--info1" || key = "--info2" || key = "--rest" then
|
||||
applyKeyValueToSubMode1State argIndex keyIndex key value state.ThingsState candidate
|
||||
else
|
||||
()
|
||||
| "Mode2" ->
|
||||
let state = candidate.CaseState :?> State_Mode2
|
||||
|
||||
if String.Equals (key, "--whatnot", StringComparison.OrdinalIgnoreCase) then
|
||||
match state.Whatnot with
|
||||
| Some _ ->
|
||||
candidate.Errors.Add (
|
||||
sprintf "Argument '--whatnot' supplied multiple times for Mode2 candidate"
|
||||
)
|
||||
|
||||
candidate.IsViable <- false
|
||||
| None ->
|
||||
try
|
||||
state.Whatnot <- Some (DateTime.Parse value)
|
||||
candidate.ConsumedArgIndices.Add argIndex |> ignore
|
||||
candidate.ConsumedArgIndices.Add keyIndex |> ignore
|
||||
with ex ->
|
||||
candidate.Errors.Add (
|
||||
sprintf "Failed to parse '%s' as DateTime for --whatnot (Mode2): %s" value ex.Message
|
||||
)
|
||||
|
||||
candidate.IsViable <- false
|
||||
elif key = "--info1" || key = "--info2" || key = "--rest" then
|
||||
applyKeyValueToSubMode2State argIndex keyIndex key value state.ThingsState candidate
|
||||
else
|
||||
()
|
||||
| _ -> failwith "Internal error: Unknown case name"
|
||||
|
||||
// processKeyValue, setFlagValue, and main loop `go` are identical to previous version
|
||||
let processKeyValue (keyIndex : int, key : string, valueIndex : int, value : string) : bool =
|
||||
let mutable handled = false
|
||||
|
||||
for candidate in candidates_WhatToDo do
|
||||
let initialConsumedCount = candidate.ConsumedArgIndices.Count
|
||||
|
||||
if candidate.IsViable then
|
||||
applyKeyValueToCandidate (valueIndex, keyIndex, key, value) candidate
|
||||
|
||||
if candidate.IsViable && candidate.ConsumedArgIndices.Count > initialConsumedCount then
|
||||
handled <- true
|
||||
consumedArgIndices_WhatToDo.Add keyIndex |> ignore
|
||||
consumedArgIndices_WhatToDo.Add valueIndex |> ignore
|
||||
|
||||
handled
|
||||
|
||||
let setFlagValue (keyIndex : int) (key : string) : bool = false // No flags
|
||||
|
||||
let rec go (state : ParseState_Args) (args : (int * string) list) =
|
||||
// ... (Implementation identical to previous version) ...
|
||||
match args with
|
||||
| [] ->
|
||||
match state with
|
||||
| ParseState_Args.AwaitingArg -> ()
|
||||
| ParseState_Args.AwaitingValue (i, k) ->
|
||||
if not (setFlagValue i k) then
|
||||
ArgParser_errors.Add (sprintf "Trailing argument '%s' (at index %d) requires a value." k i)
|
||||
| (idx, arg) :: rest ->
|
||||
match state with
|
||||
| ParseState_Args.AwaitingArg ->
|
||||
if arg = "--" then
|
||||
rest
|
||||
|> List.iter (fun (i, v) ->
|
||||
if not (consumedArgIndices_WhatToDo.Contains i) then
|
||||
arg_OtherArgs.Add v
|
||||
)
|
||||
|
||||
go ParseState_Args.AwaitingArg []
|
||||
elif arg.StartsWith ("--") then
|
||||
if arg = "--help" then
|
||||
helpText () |> failwithf "Help text requested:\n%s"
|
||||
else
|
||||
let eq = arg.IndexOf ('=')
|
||||
|
||||
if eq > 0 then
|
||||
let k = arg.[.. eq - 1]
|
||||
let v = arg.[eq + 1 ..]
|
||||
|
||||
if not (processKeyValue (idx, k, idx, v)) then
|
||||
if not (consumedArgIndices_WhatToDo.Contains idx) then
|
||||
arg_OtherArgs.Add arg
|
||||
|
||||
go ParseState_Args.AwaitingArg rest
|
||||
elif setFlagValue idx arg then
|
||||
consumedArgIndices_WhatToDo.Add idx |> ignore
|
||||
go ParseState_Args.AwaitingArg rest
|
||||
else
|
||||
go (ParseState_Args.AwaitingValue (idx, arg)) rest
|
||||
else
|
||||
if not (consumedArgIndices_WhatToDo.Contains idx) then
|
||||
arg_OtherArgs.Add arg
|
||||
|
||||
go ParseState_Args.AwaitingArg rest
|
||||
| ParseState_Args.AwaitingValue (keyIdx, key) ->
|
||||
if processKeyValue (keyIdx, key, idx, arg) then
|
||||
go ParseState_Args.AwaitingArg rest
|
||||
elif setFlagValue keyIdx key then
|
||||
consumedArgIndices_WhatToDo.Add keyIdx |> ignore<bool>
|
||||
go ParseState_Args.AwaitingArg ((idx, arg) :: rest) // Reprocess arg
|
||||
elif not (consumedArgIndices_WhatToDo.Contains keyIdx) then
|
||||
arg_OtherArgs.Add key
|
||||
|
||||
if not (consumedArgIndices_WhatToDo.Contains idx) then
|
||||
arg_OtherArgs.Add arg
|
||||
|
||||
go ParseState_Args.AwaitingArg rest
|
||||
|
||||
args |> List.mapi (fun i s -> (i, s)) |> go ParseState_Args.AwaitingArg
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Final Validation and Assembly (Uses new Assemble methods)
|
||||
//----------------------------------------------------------------------
|
||||
let viableWinners = candidates_WhatToDo |> List.filter (fun c -> c.IsViable)
|
||||
// No longer filter based on IsComplete here; Assemble handles it.
|
||||
// Still need to check for relative leftovers if that logic were implemented.
|
||||
|
||||
let whatToDoResult =
|
||||
match viableWinners with
|
||||
| [] ->
|
||||
// Add specific errors from candidates that were viable *before* Assemble check
|
||||
ArgParser_errors.Add ("No valid parse found for 'WhatToDo'.")
|
||||
|
||||
candidates_WhatToDo
|
||||
|> List.iter (fun c ->
|
||||
if c.Errors.Count <> 0 then
|
||||
ArgParser_errors.Add (
|
||||
sprintf " Candidate %s parse errors: %s" c.CaseName (String.concat "; " c.Errors)
|
||||
)
|
||||
// Potentially try to Assemble even non-viable ones to get completion errors? Maybe too complex.
|
||||
)
|
||||
|
||||
Unchecked.defaultof<_> // Error path
|
||||
|
||||
| [ winner ] ->
|
||||
// Assemble the winning case, checking the Result for completion errors
|
||||
match winner.CaseName with
|
||||
| "Mode1" ->
|
||||
match (winner.CaseState :?> State_Mode1).Assemble () with
|
||||
| Ok mode1Value -> Modes.Mode1 mode1Value
|
||||
| Error completionErrors ->
|
||||
ArgParser_errors.Add (sprintf "Validation failed for selected candidate Mode1:")
|
||||
ArgParser_errors.AddRange completionErrors
|
||||
Unchecked.defaultof<_> // Error path
|
||||
| "Mode2" ->
|
||||
match (winner.CaseState :?> State_Mode2).Assemble () with
|
||||
| Ok mode2Value -> Modes.Mode2 mode2Value
|
||||
| Error completionErrors ->
|
||||
ArgParser_errors.Add (sprintf "Validation failed for selected candidate Mode2:")
|
||||
ArgParser_errors.AddRange completionErrors
|
||||
Unchecked.defaultof<_> // Error path
|
||||
| _ -> failwith "Internal error: Unknown winning case name"
|
||||
|
||||
| winners -> // Ambiguous parse
|
||||
ArgParser_errors.Add ("Ambiguous parse for 'WhatToDo'. Multiple modes potentially viable:")
|
||||
|
||||
winners
|
||||
|> List.iter (fun c ->
|
||||
ArgParser_errors.Add (
|
||||
sprintf
|
||||
" - %s (Initial Errors: %s)"
|
||||
c.CaseName
|
||||
(if c.Errors.Count = 0 then
|
||||
"None"
|
||||
else
|
||||
String.concat "; " c.Errors)
|
||||
)
|
||||
)
|
||||
|
||||
Unchecked.defaultof<_> // Error path
|
||||
|
||||
// Finalize OtherArgs (unchanged)
|
||||
let otherArgsResult = arg_OtherArgs |> Seq.toList
|
||||
|
||||
// Assemble Final Result or Fail (unchanged)
|
||||
if ArgParser_errors.Count > 0 then
|
||||
ArgParser_errors
|
||||
|> String.concat "\n"
|
||||
|> failwithf "Errors during parse!\n%s\n\nHelp Text:\n%s" (helpText ())
|
||||
else
|
||||
{
|
||||
WhatToDo = whatToDoResult
|
||||
OtherArgs = otherArgsResult
|
||||
}
|
||||
|
||||
let parse (args : string list) : Args =
|
||||
parse' System.Environment.GetEnvironmentVariable args
|
19
Playground/Playground.fsproj
Normal file
19
Playground/Playground.fsproj
Normal file
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Domain.fs" />
|
||||
<Compile Include="Library.fs"/>
|
||||
<Compile Include="Program.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WoofWare.Myriad.Plugins.Attributes\WoofWare.Myriad.Plugins.Attributes.fsproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
10
Playground/Program.fs
Normal file
10
Playground/Program.fs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Playground
|
||||
|
||||
module Program =
|
||||
[<EntryPoint>]
|
||||
let main argv =
|
||||
[ "--whatnot=2024-01-12" ; "--info1=4" ; "--info2=hi" ]
|
||||
|> Args.parse
|
||||
|> printfn "%O"
|
||||
|
||||
0
|
@@ -26,6 +26,11 @@ type ArgParserAttribute (isExtensionMethod : bool) =
|
||||
/// an argument which looks like a flag but which we don't recognise.)
|
||||
/// We will still interpret `--help` as requesting help, unless it comes after
|
||||
/// a standalone `--` separator.
|
||||
///
|
||||
/// If the type of the PositionalArgs field is `Choice<'a, 'a>`, then we will
|
||||
/// tell you whether each arg came before or after a standalone `--` separator.
|
||||
/// For example, `MyApp foo bar -- baz` with PositionalArgs of `Choice<string, string>`
|
||||
/// would yield `Choice1Of2 foo, Choice1Of2 bar, Choice2Of2 baz`.
|
||||
type PositionalArgsAttribute (includeFlagLike : bool) =
|
||||
inherit Attribute ()
|
||||
|
||||
|
@@ -17,10 +17,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ApiSurface" Version="4.1.14" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
|
||||
<PackageReference Include="NUnit" Version="4.3.0"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
|
||||
<PackageReference Include="ApiSurface" Version="4.1.20" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0"/>
|
||||
<PackageReference Include="NUnit" Version="4.3.2"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -79,11 +79,8 @@ module TestArgParser =
|
||||
|
||||
exc.Message
|
||||
|> shouldEqual
|
||||
"""Unable to process supplied arg --non-existent. Help text follows.
|
||||
--foo int32 : This is a foo!
|
||||
--bar string
|
||||
--baz bool
|
||||
--rest string (positional args) (can be repeated) : Here's where the rest of the args go"""
|
||||
"""Errors during parse!
|
||||
Unmatched args which look like they are meant to be flags. If you intended them as positional args, explicitly pass them with the `--rest=` syntax, or place them after a trailing `--`. --non-existent"""
|
||||
|
||||
[<Test>]
|
||||
let ``Can supply positional args with key`` () =
|
||||
@@ -318,8 +315,7 @@ Required argument '--baz' received no value"""
|
||||
exc.Message
|
||||
|> shouldEqual
|
||||
"""Errors during parse!
|
||||
Input string was not in a correct format. (at arg --invariant-exact=23:59)
|
||||
Required argument '--invariant-exact' received no value"""
|
||||
Input string was not in a correct format. (at arg --invariant-exact=23:59)"""
|
||||
|
||||
let exc =
|
||||
Assert.Throws<exn> (fun () ->
|
||||
@@ -337,8 +333,7 @@ Required argument '--invariant-exact' received no value"""
|
||||
exc.Message
|
||||
|> shouldEqual
|
||||
"""Errors during parse!
|
||||
Input string was not in a correct format. (at arg --exact=11:34)
|
||||
Required argument '--exact' received no value"""
|
||||
Input string was not in a correct format. (at arg --exact=11:34)"""
|
||||
|
||||
count.Value |> shouldEqual 0
|
||||
|
||||
@@ -444,7 +439,7 @@ Required argument '--exact' received no value"""
|
||||
]
|
||||
|> List.map TestCaseData
|
||||
|
||||
[<TestCaseSource(nameof (boolCases))>]
|
||||
[<TestCaseSource(nameof boolCases)>]
|
||||
let ``Bool env vars can be populated`` (envValue : string, boolValue : bool) =
|
||||
let getEnvVar (s : string) =
|
||||
s |> shouldEqual "CONSUMEPLUGIN_THINGS"
|
||||
@@ -604,7 +599,10 @@ Required argument '--exact' received no value"""
|
||||
)
|
||||
|
||||
exc.Message
|
||||
|> shouldEqual """Unable to process argument --do-the-thing=foo as key --do-the-thing and value foo"""
|
||||
|> shouldEqual
|
||||
"""Errors during parse!
|
||||
Required argument '--do-something-else' received no value
|
||||
Required argument '--turn-it-on' received no value"""
|
||||
|
||||
[<Test>]
|
||||
let ``Long-form args help text`` () =
|
||||
@@ -692,7 +690,9 @@ Required argument '--exact' received no value"""
|
||||
)
|
||||
|
||||
exc.Message
|
||||
|> shouldEqual """Unable to process argument --b=false as key --b and value false"""
|
||||
|> shouldEqual
|
||||
"""Errors during parse!
|
||||
Unmatched args which look like they are meant to be flags. If you intended them as positional args, explicitly pass them with the `--dont-grab-everything=` syntax, or place them after a trailing `--`. --b=false --c"""
|
||||
|
||||
let exc =
|
||||
Assert.Throws<exn> (fun () ->
|
||||
@@ -703,4 +703,6 @@ Required argument '--exact' received no value"""
|
||||
// Again perhaps eccentric!
|
||||
// Again, we don't try to detect that the user has missed out the desired argument to `--a`.
|
||||
exc.Message
|
||||
|> shouldEqual """Unable to process argument --c=hi as key --c and value hi"""
|
||||
|> shouldEqual
|
||||
"""Errors during parse!
|
||||
Unmatched args which look like they are meant to be flags. If you intended them as positional args, explicitly pass them with the `--my-arg-name=` syntax, or place them after a trailing `--`. --c=hi"""
|
||||
|
@@ -0,0 +1,21 @@
|
||||
namespace WoofWare.Myriad.Plugins.Test
|
||||
|
||||
open FsUnitTyped
|
||||
open NUnit.Framework
|
||||
open ConsumePlugin.ArgsWithUnions
|
||||
|
||||
[<TestFixture>]
|
||||
module TestArgsWithUnions =
|
||||
|
||||
let argsWithUnionsCases =
|
||||
[
|
||||
["--token" ; "hello" ; "--foo" ; "3" ; "--bar=hi" ; "--baz"], { Auth = AuthOptions.Token { Token = "hello" } ; Basics = { Foo = 3 ; Bar = "hi" ; Baz = true ; Rest = [] } }
|
||||
]
|
||||
|> List.map TestCaseData
|
||||
|
||||
[<TestCaseSource (nameof argsWithUnionsCases)>]
|
||||
let ``foo`` (args : string list, expected : DoTheThing) : unit =
|
||||
args
|
||||
|> DoTheThing.parse' (fun _ -> failwith "didn't expect env var")
|
||||
|> shouldEqual expected
|
||||
|
@@ -3,7 +3,7 @@ namespace WoofWare.Myriad.Plugins.Test
|
||||
open System
|
||||
open System.Collections.Generic
|
||||
open System.Text.Json.Nodes
|
||||
open FsCheck.Random
|
||||
open FsCheck.FSharp
|
||||
open Microsoft.FSharp.Reflection
|
||||
open NUnit.Framework
|
||||
open FsCheck
|
||||
@@ -15,21 +15,21 @@ module TestJsonSerde =
|
||||
|
||||
let uriGen : Gen<Uri> =
|
||||
gen {
|
||||
let! suffix = Arb.generate<int>
|
||||
let! suffix = ArbMap.generate<int> ArbMap.defaults
|
||||
return Uri $"https://example.com/%i{suffix}"
|
||||
}
|
||||
|
||||
let rec innerGen (count : int) : Gen<InnerTypeWithBoth> =
|
||||
gen {
|
||||
let! guid = Arb.generate<Guid>
|
||||
let! mapKeys = Gen.listOf Arb.generate<NonNull<string>>
|
||||
let! guid = ArbMap.generate<Guid> ArbMap.defaults
|
||||
let! mapKeys = Gen.listOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
|
||||
let mapKeys = mapKeys |> List.map _.Get |> List.distinct
|
||||
let! mapValues = Gen.listOfLength mapKeys.Length uriGen
|
||||
let map = List.zip mapKeys mapValues |> Map.ofList
|
||||
|
||||
let! concreteDictKeys =
|
||||
if count > 0 then
|
||||
Gen.listOf Arb.generate<NonNull<string>>
|
||||
Gen.listOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
|
||||
else
|
||||
Gen.constant []
|
||||
|
||||
@@ -50,13 +50,16 @@ module TestJsonSerde =
|
||||
|> List.map KeyValuePair
|
||||
|> Dictionary
|
||||
|
||||
let! readOnlyDictKeys = Gen.listOf Arb.generate<NonNull<string>>
|
||||
let! readOnlyDictKeys = Gen.listOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
|
||||
let readOnlyDictKeys = readOnlyDictKeys |> List.map _.Get |> List.distinct
|
||||
let! readOnlyDictValues = Gen.listOfLength readOnlyDictKeys.Length (Gen.listOf Arb.generate<char>)
|
||||
|
||||
let! readOnlyDictValues =
|
||||
Gen.listOfLength readOnlyDictKeys.Length (Gen.listOf (ArbMap.generate<char> ArbMap.defaults))
|
||||
|
||||
let readOnlyDict = List.zip readOnlyDictKeys readOnlyDictValues |> readOnlyDict
|
||||
|
||||
let! dictKeys = Gen.listOf uriGen
|
||||
let! dictValues = Gen.listOfLength dictKeys.Length Arb.generate<bool>
|
||||
let! dictValues = Gen.listOfLength dictKeys.Length (ArbMap.generate<bool> ArbMap.defaults)
|
||||
let dict = List.zip dictKeys dictValues |> dict
|
||||
|
||||
return
|
||||
@@ -71,28 +74,38 @@ module TestJsonSerde =
|
||||
|
||||
let outerGen : Gen<JsonRecordTypeWithBoth> =
|
||||
gen {
|
||||
let! a = Arb.generate<int>
|
||||
let! b = Arb.generate<NonNull<string>>
|
||||
let! c = Gen.listOf Arb.generate<int>
|
||||
let! a = ArbMap.generate<int> ArbMap.defaults
|
||||
let! b = ArbMap.generate<NonNull<string>> ArbMap.defaults
|
||||
let! c = Gen.listOf (ArbMap.generate<int> ArbMap.defaults)
|
||||
let! depth = Gen.choose (0, 2)
|
||||
let! d = innerGen depth
|
||||
let! e = Gen.arrayOf Arb.generate<NonNull<string>>
|
||||
let! arr = Gen.arrayOf Arb.generate<int>
|
||||
let! byte = Arb.generate
|
||||
let! sbyte = Arb.generate
|
||||
let! i = Arb.generate
|
||||
let! i32 = Arb.generate
|
||||
let! i64 = Arb.generate
|
||||
let! u = Arb.generate
|
||||
let! u32 = Arb.generate
|
||||
let! u64 = Arb.generate
|
||||
let! f = Arb.generate |> Gen.filter (fun s -> Double.IsFinite (s / 1.0<measure>))
|
||||
let! f32 = Arb.generate |> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
|
||||
let! single = Arb.generate |> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
|
||||
let! intMeasureOption = Arb.generate
|
||||
let! intMeasureNullable = Arb.generate
|
||||
let! e = Gen.arrayOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
|
||||
let! arr = Gen.arrayOf (ArbMap.generate<int> ArbMap.defaults)
|
||||
let! byte = ArbMap.generate ArbMap.defaults
|
||||
let! sbyte = ArbMap.generate ArbMap.defaults
|
||||
let! i = ArbMap.generate ArbMap.defaults
|
||||
let! i32 = ArbMap.generate ArbMap.defaults
|
||||
let! i64 = ArbMap.generate ArbMap.defaults
|
||||
let! u = ArbMap.generate ArbMap.defaults
|
||||
let! u32 = ArbMap.generate ArbMap.defaults
|
||||
let! u64 = ArbMap.generate ArbMap.defaults
|
||||
|
||||
let! f =
|
||||
ArbMap.generate ArbMap.defaults
|
||||
|> Gen.filter (fun s -> Double.IsFinite (s / 1.0<measure>))
|
||||
|
||||
let! f32 =
|
||||
ArbMap.generate ArbMap.defaults
|
||||
|> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
|
||||
|
||||
let! single =
|
||||
ArbMap.generate ArbMap.defaults
|
||||
|> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
|
||||
|
||||
let! intMeasureOption = ArbMap.generate ArbMap.defaults
|
||||
let! intMeasureNullable = ArbMap.generate ArbMap.defaults
|
||||
let! someEnum = Gen.choose (0, 1)
|
||||
let! timestamp = Arb.generate
|
||||
let! timestamp = ArbMap.generate ArbMap.defaults
|
||||
|
||||
return
|
||||
{
|
||||
@@ -270,10 +283,10 @@ module TestJsonSerde =
|
||||
match case with
|
||||
| 0 -> return FirstDu.EmptyCase
|
||||
| 1 ->
|
||||
let! s = Arb.generate<NonNull<string>>
|
||||
let! s = ArbMap.generate<NonNull<string>> ArbMap.defaults
|
||||
return FirstDu.Case1 s.Get
|
||||
| 2 ->
|
||||
let! i = Arb.generate<int>
|
||||
let! i = ArbMap.generate<int> ArbMap.defaults
|
||||
let! record = outerGen
|
||||
return FirstDu.Case2 (record, i)
|
||||
| _ -> return failwith $"unexpected: %i{case}"
|
||||
@@ -293,7 +306,6 @@ module TestJsonSerde =
|
||||
|
||||
[<Test>]
|
||||
let ``DU generator covers all cases`` () =
|
||||
let rand = Random ()
|
||||
let cases = FSharpType.GetUnionCases typeof<FirstDu>
|
||||
let counts = Array.zeroCreate<int> cases.Length
|
||||
|
||||
@@ -301,11 +313,13 @@ module TestJsonSerde =
|
||||
|
||||
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 property (du : FirstDu) =
|
||||
let tag = decompose du
|
||||
counts.[tag] <- counts.[tag] + 1
|
||||
i <- i + 1
|
||||
true
|
||||
|
||||
Check.One (Config.Quick, Prop.forAll (Arb.fromGen duGen) property)
|
||||
|
||||
for i in counts do
|
||||
i |> shouldBeGreaterThan 0
|
||||
|
@@ -34,3 +34,16 @@ module TestMockGenerator =
|
||||
mock.Mem1 3 'a' |> shouldEqual "aaa"
|
||||
mock.Mem2 (3, "hi") 'a' |> shouldEqual "hiahiahi"
|
||||
mock.Mem3 (3, "hi") 'a' |> shouldEqual "hiahiahi"
|
||||
|
||||
[<Test>]
|
||||
let ``Example of use: properties`` () =
|
||||
let mock : TypeWithProperties =
|
||||
{ TypeWithPropertiesMock.Empty with
|
||||
Mem1 = fun i -> async { return Option.toArray i }
|
||||
Prop1 = fun () -> 44
|
||||
}
|
||||
:> _
|
||||
|
||||
mock.Mem1 (Some "hi") |> Async.RunSynchronously |> shouldEqual [| "hi" |]
|
||||
|
||||
mock.Prop1 |> shouldEqual 44
|
||||
|
@@ -9,9 +9,11 @@
|
||||
I have not yet seen a single instance where I care about this warning
|
||||
-->
|
||||
<NoWarn>$(NoWarn),NU1903</NoWarn>
|
||||
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--
|
||||
<Compile Include="HttpClient.fs"/>
|
||||
<Compile Include="PureGymDtos.fs"/>
|
||||
<Compile Include="TestJsonParse\TestJsonParse.fs" />
|
||||
@@ -33,20 +35,24 @@
|
||||
<Compile Include="TestCataGenerator\TestGift.fs" />
|
||||
<Compile Include="TestCataGenerator\TestMyList.fs" />
|
||||
<Compile Include="TestCataGenerator\TestMyList2.fs" />
|
||||
-->
|
||||
<Compile Include="TestArgParser\TestArgParser.fs" />
|
||||
<Compile Include="TestArgParser\TestArgsWithUnions.fs" />
|
||||
<!--
|
||||
<Compile Include="TestSwagger\TestSwaggerParse.fs" />
|
||||
<Compile Include="TestRemoveOptions.fs"/>
|
||||
<Compile Include="TestSurface.fs"/>
|
||||
-->
|
||||
<None Include="../.github/workflows/dotnet.yaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ApiSurface" Version="4.1.14"/>
|
||||
<PackageReference Include="FsCheck" Version="2.16.6"/>
|
||||
<PackageReference Include="FsUnit" Version="6.0.1"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
|
||||
<PackageReference Include="NUnit" Version="4.3.0"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
|
||||
<PackageReference Include="ApiSurface" Version="4.1.20"/>
|
||||
<PackageReference Include="FsCheck" Version="3.2.0"/>
|
||||
<PackageReference Include="FsUnit" Version="7.0.1"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0"/>
|
||||
<PackageReference Include="NUnit" Version="4.3.2"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -7,82 +7,6 @@ open Fantomas.FCS.Text.Range
|
||||
open TypeEquality
|
||||
open WoofWare.Whippet.Fantomas
|
||||
|
||||
type internal ArgParserOutputSpec =
|
||||
{
|
||||
ExtensionMethods : bool
|
||||
}
|
||||
|
||||
type internal FlagDu =
|
||||
{
|
||||
Name : Ident
|
||||
Case1Name : Ident
|
||||
Case2Name : Ident
|
||||
/// Hopefully this is simply the const bool True or False, but it might e.g. be a literal
|
||||
Case1Arg : SynExpr
|
||||
/// Hopefully this is simply the const bool True or False, but it might e.g. be a literal
|
||||
Case2Arg : SynExpr
|
||||
}
|
||||
|
||||
static member FromBoolean (flagDu : FlagDu) (value : SynExpr) =
|
||||
SynExpr.ifThenElse
|
||||
(SynExpr.equals value flagDu.Case1Arg)
|
||||
(SynExpr.createLongIdent' [ flagDu.Name ; flagDu.Case2Name ])
|
||||
(SynExpr.createLongIdent' [ flagDu.Name ; flagDu.Case1Name ])
|
||||
|
||||
/// The default value of an argument which admits default values can be pulled from different sources.
|
||||
/// This defines which source a particular default value comes from.
|
||||
type private ArgumentDefaultSpec =
|
||||
/// From parsing the environment variable with the given name (e.g. "WOOFWARE_DISABLE_FOO" or whatever).
|
||||
| EnvironmentVariable of name : SynExpr
|
||||
/// From calling the static member `{typeWeParseInto}.Default{name}()`
|
||||
/// For example, if `type MyArgs = { Thing : Choice<int, int> }`, then
|
||||
/// we would use `MyArgs.DefaultThing () : int`.
|
||||
///
|
||||
| FunctionCall of name : Ident
|
||||
|
||||
type private Accumulation<'choice> =
|
||||
| Required
|
||||
| Optional
|
||||
| Choice of 'choice
|
||||
| List of Accumulation<'choice>
|
||||
|
||||
type private ParseFunction<'acc> =
|
||||
{
|
||||
FieldName : Ident
|
||||
TargetVariable : Ident
|
||||
/// Any of the forms in this set are acceptable, but make sure they all start with a dash, or we might
|
||||
/// get confused with positional args or something! I haven't thought that hard about this.
|
||||
/// In the default case, this is `Const("arg-name")` for the `ArgName : blah` field; note that we have
|
||||
/// omitted the initial `--` that will be required at runtime.
|
||||
ArgForm : SynExpr list
|
||||
/// If this is a boolean-like field (e.g. a bool or a flag DU), the help text should look a bit different:
|
||||
/// we should lie to the user about the value of the cases there.
|
||||
/// Similarly, if we're reading from an environment variable with the laxer parsing rules of accepting e.g.
|
||||
/// "0" instead of "false", we need to know if we're reading a bool.
|
||||
/// In that case, `boolCases` is Some, and contains the construction of the flag (or boolean, in which case
|
||||
/// you get no data).
|
||||
BoolCases : Choice<FlagDu, unit> option
|
||||
Help : SynExpr option
|
||||
/// A function string -> %TargetType%, where TargetVariable is probably a `%TargetType% option`.
|
||||
/// (Depending on `Accumulation`, we'll remove the `option` at the end of the parse, asserting that the
|
||||
/// argument was supplied.)
|
||||
/// This is allowed to throw if it fails to parse.
|
||||
Parser : SynExpr
|
||||
/// If `Accumulation` is `List`, then this is the type of the list *element*; analogously for optionals
|
||||
/// and choices and so on.
|
||||
TargetType : SynType
|
||||
Accumulation : 'acc
|
||||
}
|
||||
|
||||
/// A SynExpr of type `string` which we can display to the user at generated-program runtime to display all
|
||||
/// the ways they can refer to this arg.
|
||||
member arg.HumanReadableArgForm : SynExpr =
|
||||
let formatString = List.replicate arg.ArgForm.Length "--%s" |> String.concat " / "
|
||||
|
||||
(SynExpr.applyFunction (SynExpr.createIdent "sprintf") (SynExpr.CreateConst formatString), arg.ArgForm)
|
||||
||> List.fold SynExpr.applyFunction
|
||||
|> SynExpr.paren
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
type private ChoicePositional =
|
||||
| Normal of includeFlagLike : SynExpr option
|
||||
@@ -114,14 +38,14 @@ type private ParseTree<'hasPositional> =
|
||||
/// `assemble` takes the SynExpr's (e.g. each record field contents) corresponding to each `Ident` in
|
||||
/// the branch (e.g. each record field name),
|
||||
/// and composes them into a `SynExpr` (e.g. the record-typed object).
|
||||
| Branch of
|
||||
| DescendRecord of
|
||||
fields : (Ident * ParseTree<HasNoPositional>) list *
|
||||
assemble : (Map<string, SynExpr> -> SynExpr) *
|
||||
Teq<'hasPositional, HasNoPositional>
|
||||
/// `assemble` takes the SynExpr's (e.g. each record field contents) corresponding to each `Ident` in
|
||||
/// the branch (e.g. each record field name),
|
||||
/// and composes them into a `SynExpr` (e.g. the record-typed object).
|
||||
| BranchPos of
|
||||
| DescendRecordPos of
|
||||
posField : Ident *
|
||||
fields : ParseTree<HasPositional> *
|
||||
(Ident * ParseTree<HasNoPositional>) list *
|
||||
@@ -184,63 +108,6 @@ module private ParseTree =
|
||||
|
||||
go None ([], None) subs
|
||||
|
||||
let rec accumulatorsNonPos (tree : ParseTree<HasNoPositional>) : ParseFunctionNonPositional list =
|
||||
match tree with
|
||||
| ParseTree.PositionalLeaf (_, teq) -> exFalso teq
|
||||
| ParseTree.BranchPos (_, _, _, _, teq) -> exFalso teq
|
||||
| ParseTree.NonPositionalLeaf (pf, _) -> [ pf ]
|
||||
| ParseTree.Branch (trees, _, _) -> trees |> List.collect (snd >> accumulatorsNonPos)
|
||||
|
||||
/// Returns the positional arg separately.
|
||||
let rec accumulatorsPos
|
||||
(tree : ParseTree<HasPositional>)
|
||||
: ParseFunctionNonPositional list * ParseFunctionPositional
|
||||
=
|
||||
match tree with
|
||||
| ParseTree.PositionalLeaf (pf, _) -> [], pf
|
||||
| ParseTree.NonPositionalLeaf (_, teq) -> exFalso' teq
|
||||
| ParseTree.Branch (_, _, teq) -> exFalso' teq
|
||||
| ParseTree.BranchPos (_, tree, trees, _, _) ->
|
||||
let nonPos = trees |> List.collect (snd >> accumulatorsNonPos)
|
||||
|
||||
let nonPos2, pos = accumulatorsPos tree
|
||||
nonPos @ nonPos2, pos
|
||||
|
||||
/// Collect all the ParseFunctions which are necessary to define variables, throwing away
|
||||
/// all information relevant to composing the resulting variables into records.
|
||||
/// Returns the list of non-positional parsers, and any positional parser that exists.
|
||||
let accumulators<'a> (tree : ParseTree<'a>) : ParseFunctionNonPositional list * ParseFunctionPositional option =
|
||||
// Sad duplication of some code here, but it was the easiest way to make it type-safe :(
|
||||
match tree with
|
||||
| ParseTree.PositionalLeaf (pf, _) -> [], Some pf
|
||||
| ParseTree.NonPositionalLeaf (pf, _) -> [ pf ], None
|
||||
| ParseTree.Branch (trees, _, _) -> trees |> List.collect (snd >> accumulatorsNonPos) |> (fun i -> i, None)
|
||||
| ParseTree.BranchPos (_, tree, trees, _, _) ->
|
||||
let nonPos = trees |> List.collect (snd >> accumulatorsNonPos)
|
||||
|
||||
let nonPos2, pos = accumulatorsPos tree
|
||||
nonPos @ nonPos2, Some pos
|
||||
|
||||
|> fun (nonPos, pos) ->
|
||||
let duplicateArgs =
|
||||
// This is best-effort. We can't necessarily detect all SynExprs here, but usually it'll be strings.
|
||||
Option.toList (pos |> Option.map _.ArgForm) @ (nonPos |> List.map _.ArgForm)
|
||||
|> Seq.concat
|
||||
|> Seq.choose (fun expr ->
|
||||
match expr |> SynExpr.stripOptionalParen with
|
||||
| SynExpr.Const (SynConst.String (s, _, _), _) -> Some s
|
||||
| _ -> None
|
||||
)
|
||||
|> List.ofSeq
|
||||
|> List.groupBy id
|
||||
|> List.choose (fun (key, v) -> if v.Length > 1 then Some key else None)
|
||||
|
||||
match duplicateArgs with
|
||||
| [] -> nonPos, pos
|
||||
| dups ->
|
||||
let dups = dups |> String.concat " "
|
||||
failwith $"Duplicate args detected! %s{dups}"
|
||||
|
||||
/// Build the return value.
|
||||
let rec instantiate<'a> (tree : ParseTree<'a>) : SynExpr =
|
||||
match tree with
|
||||
@@ -673,7 +540,7 @@ module internal ArgParserGenerator =
|
||||
args
|
||||
|> Map.toList
|
||||
|> List.map (fun (ident, expr) -> SynLongIdent.create [ Ident.create ident ], expr)
|
||||
|> AstHelper.instantiateRecord
|
||||
|> SynExpr.createRecord None
|
||||
)
|
||||
|
||||
tree, counter
|
||||
|
@@ -36,13 +36,6 @@ module internal AstHelper =
|
||||
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Enum _, _) -> true
|
||||
| _ -> false
|
||||
|
||||
let instantiateRecord (fields : (SynLongIdent * SynExpr) list) : SynExpr =
|
||||
let fields =
|
||||
fields
|
||||
|> List.map (fun (rfn, synExpr) -> SynExprRecordField ((rfn, true), Some range0, Some synExpr, None))
|
||||
|
||||
SynExpr.Record (None, None, fields, range0)
|
||||
|
||||
let defineRecordType (record : RecordType) : SynTypeDefn =
|
||||
let name =
|
||||
SynComponentInfo.create record.Name
|
||||
|
@@ -89,7 +89,7 @@ module internal InterfaceMockGenerator =
|
||||
[]
|
||||
else
|
||||
[ SynPat.unit ])
|
||||
(AstHelper.instantiateRecord constructorFields)
|
||||
(SynExpr.createRecord None constructorFields)
|
||||
|> SynBinding.withXmlDoc (PreXmlDoc.create "An implementation where every method throws.")
|
||||
|> SynBinding.withReturnAnnotation constructorReturnType
|
||||
|> SynMemberDefn.staticMember
|
||||
@@ -159,6 +159,15 @@ module internal InterfaceMockGenerator =
|
||||
|> SynMemberDefn.memberImplementation
|
||||
)
|
||||
|
||||
let properties =
|
||||
interfaceType.Properties
|
||||
|> List.map (fun pi ->
|
||||
SynExpr.createLongIdent' [ Ident.create "this" ; pi.Identifier ]
|
||||
|> SynExpr.applyTo (SynExpr.CreateConst ())
|
||||
|> SynBinding.basic [ Ident.create "this" ; pi.Identifier ] []
|
||||
|> SynMemberDefn.memberImplementation
|
||||
)
|
||||
|
||||
let interfaceName =
|
||||
let baseName = SynType.createLongIdent interfaceType.Name
|
||||
|
||||
@@ -174,7 +183,7 @@ module internal InterfaceMockGenerator =
|
||||
|
||||
SynType.app' baseName generics
|
||||
|
||||
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
||||
SynMemberDefn.Interface (interfaceName, Some range0, Some (members @ properties), range0)
|
||||
|
||||
let access =
|
||||
match interfaceType.Accessibility, spec.IsInternal with
|
||||
@@ -248,6 +257,15 @@ module internal InterfaceMockGenerator =
|
||||
|> SynField.make
|
||||
|> SynField.withDocString (mem.XmlDoc |> Option.defaultValue PreXmlDoc.Empty)
|
||||
|
||||
let constructProperty (prop : PropertyInfo) : SynField =
|
||||
{
|
||||
Attrs = []
|
||||
Ident = Some prop.Identifier
|
||||
Type = SynType.toFun [ SynType.unit ] prop.Type
|
||||
}
|
||||
|> SynField.make
|
||||
|> SynField.withDocString (prop.XmlDoc |> Option.defaultValue PreXmlDoc.Empty)
|
||||
|
||||
let createRecord
|
||||
(namespaceId : LongIdent)
|
||||
(opens : SynOpenDeclTarget list)
|
||||
@@ -255,7 +273,12 @@ module internal InterfaceMockGenerator =
|
||||
: SynModuleOrNamespace
|
||||
=
|
||||
let interfaceType = AstHelper.parseInterface interfaceType
|
||||
let fields = interfaceType.Members |> List.map constructMember
|
||||
|
||||
let fields =
|
||||
interfaceType.Members
|
||||
|> List.map constructMember
|
||||
|> List.append (interfaceType.Properties |> List.map constructProperty)
|
||||
|
||||
let docString = PreXmlDoc.create "Mock record type for an interface"
|
||||
|
||||
let name =
|
||||
|
@@ -351,10 +351,7 @@ module internal JsonParseGenerator =
|
||||
let getParseOptions (fieldAttrs : SynAttribute list) =
|
||||
(JsonParseOption.None, fieldAttrs)
|
||||
||> List.fold (fun options attr ->
|
||||
if
|
||||
(SynLongIdent.toString attr.TypeName)
|
||||
.EndsWith ("JsonNumberHandling", StringComparison.Ordinal)
|
||||
then
|
||||
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 ->
|
||||
@@ -384,15 +381,13 @@ module internal JsonParseGenerator =
|
||||
let propertyNameAttr =
|
||||
fieldData.Attrs
|
||||
|> List.tryFind (fun attr ->
|
||||
(SynLongIdent.toString attr.TypeName)
|
||||
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||
)
|
||||
|
||||
let extensionDataAttr =
|
||||
fieldData.Attrs
|
||||
|> List.tryFind (fun attr ->
|
||||
(SynLongIdent.toString attr.TypeName)
|
||||
.EndsWith ("JsonExtensionData", StringComparison.Ordinal)
|
||||
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonExtensionData", StringComparison.Ordinal)
|
||||
)
|
||||
|
||||
let propertyName =
|
||||
@@ -485,7 +480,7 @@ module internal JsonParseGenerator =
|
||||
let finalConstruction =
|
||||
fields
|
||||
|> List.mapi (fun i fieldData -> SynLongIdent.createI fieldData.Ident, SynExpr.createIdent $"arg_%i{i}")
|
||||
|> AstHelper.instantiateRecord
|
||||
|> SynExpr.createRecord None
|
||||
|
||||
(finalConstruction, assignments)
|
||||
||> List.fold (fun final assignment -> SynExpr.createLet [ assignment ] final)
|
||||
|
@@ -180,8 +180,7 @@ module internal JsonSerializeGenerator =
|
||||
let propertyNameAttr =
|
||||
attrs
|
||||
|> List.tryFind (fun attr ->
|
||||
(SynLongIdent.toString attr.TypeName)
|
||||
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonPropertyName", StringComparison.Ordinal)
|
||||
)
|
||||
|
||||
match propertyNameAttr with
|
||||
@@ -198,8 +197,7 @@ module internal JsonSerializeGenerator =
|
||||
let getIsJsonExtension (attrs : SynAttribute list) : bool =
|
||||
attrs
|
||||
|> List.tryFind (fun attr ->
|
||||
(SynLongIdent.toString attr.TypeName)
|
||||
.EndsWith ("JsonExtensionData", StringComparison.Ordinal)
|
||||
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonExtensionData", StringComparison.Ordinal)
|
||||
)
|
||||
|> Option.isSome
|
||||
|
||||
|
@@ -21,3 +21,13 @@ module private List =
|
||||
| Some head :: tail -> go (head :: acc) tail
|
||||
|
||||
go [] l
|
||||
|
||||
/// Return the first error encountered, or the entire list.
|
||||
let allOkOrError<'ok, 'err> (l : Result<'ok, 'err> list) : Result<'ok list, 'err> =
|
||||
let rec go acc l =
|
||||
match l with
|
||||
| [] -> Ok (List.rev acc)
|
||||
| Error e :: _ -> Error e
|
||||
| Ok o :: rest -> go (o :: acc) rest
|
||||
|
||||
go [] l
|
||||
|
@@ -97,7 +97,7 @@ module internal RemoveOptionsGenerator =
|
||||
|
||||
SynLongIdent.createI fieldData.Ident, body
|
||||
)
|
||||
|> AstHelper.instantiateRecord
|
||||
|> SynExpr.createRecord None
|
||||
|
||||
SynBinding.basic
|
||||
[ functionName ]
|
||||
|
2659
WoofWare.Myriad.Plugins/ShibaGenerator.fs
Normal file
2659
WoofWare.Myriad.Plugins/ShibaGenerator.fs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Myriad.Core" Version="0.8.3" />
|
||||
<PackageReference Include="TypeEquality" Version="0.3.0" />
|
||||
<PackageReference Include="WoofWare.Whippet.Fantomas" Version="0.3.1" />
|
||||
<PackageReference Include="WoofWare.Whippet.Fantomas" Version="0.5.1" />
|
||||
<!-- the lowest version allowed by Myriad.Core -->
|
||||
<PackageReference Update="FSharp.Core" Version="6.0.1" PrivateAssets="all"/>
|
||||
</ItemGroup>
|
||||
@@ -40,7 +40,8 @@
|
||||
<Compile Include="JsonParseGenerator.fs"/>
|
||||
<Compile Include="HttpClientGenerator.fs"/>
|
||||
<Compile Include="CataGenerator.fs" />
|
||||
<Compile Include="ArgParserGenerator.fs" />
|
||||
<Compile Include="ShibaGenerator.fs" />
|
||||
<None Include="ArgParserGenerator.fs" />
|
||||
<Compile Include="Swagger.fs" />
|
||||
<Compile Include="SwaggerClientGenerator.fs" />
|
||||
<None Include="ApacheLicence.txt" />
|
||||
|
@@ -10,6 +10,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WoofWare.Myriad.Plugins.Att
|
||||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WoofWare.Myriad.Plugins.Attributes.Test", "WoofWare.Myriad.Plugins.Attributes\Test\WoofWare.Myriad.Plugins.Attributes.Test.fsproj", "{26DC0C94-85F2-45B4-8FA1-1B27201F7AFB}"
|
||||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Playground", "Playground\Playground.fsproj", "{6DF8C756-DE59-4AFF-A4BB-2D05C74192A4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -36,5 +38,9 @@ Global
|
||||
{26DC0C94-85F2-45B4-8FA1-1B27201F7AFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{26DC0C94-85F2-45B4-8FA1-1B27201F7AFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{26DC0C94-85F2-45B4-8FA1-1B27201F7AFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6DF8C756-DE59-4AFF-A4BB-2D05C74192A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6DF8C756-DE59-4AFF-A4BB-2D05C74192A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6DF8C756-DE59-4AFF-A4BB-2D05C74192A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6DF8C756-DE59-4AFF-A4BB-2D05C74192A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.12.0]" />
|
||||
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.14.0]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
6
flake.lock
generated
6
flake.lock
generated
@@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1734126203,
|
||||
"narHash": "sha256-0XovF7BYP50rTD2v4r55tR5MuBLet7q4xIz6Rgh3BBU=",
|
||||
"lastModified": 1744502386,
|
||||
"narHash": "sha256-QAd1L37eU7ktL2WeLLLTmI6P9moz9+a/ONO8qNBYJgM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "71a6392e367b08525ee710a93af2e80083b5b3e2",
|
||||
"rev": "f6db44a8daa59c40ae41ba6e5823ec77fe0d2124",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
10
flake.nix
10
flake.nix
@@ -44,9 +44,11 @@
|
||||
'';
|
||||
};
|
||||
in {
|
||||
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;}))).hash;
|
||||
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;}))).hash;
|
||||
packages = let
|
||||
deps = builtins.fromJSON (builtins.readFile ./nix/deps.json);
|
||||
in {
|
||||
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") deps)).hash;
|
||||
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") deps)).hash;
|
||||
default = pkgs.buildDotnetModule {
|
||||
inherit pname version dotnet-sdk dotnet-runtime;
|
||||
name = "WoofWare.Myriad.Plugins";
|
||||
@@ -54,7 +56,7 @@
|
||||
projectFile = "./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj";
|
||||
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 nix/deps.nix`
|
||||
nugetDeps = ./nix/deps.json; # `nix build .#default.fetch-deps && ./result nix/deps.json`
|
||||
doCheck = true;
|
||||
};
|
||||
};
|
||||
|
387
nix/deps.json
Normal file
387
nix/deps.json
Normal file
@@ -0,0 +1,387 @@
|
||||
[
|
||||
{
|
||||
"pname": "ApiSurface",
|
||||
"version": "4.1.20",
|
||||
"hash": "sha256-koWgO9FC9ax+Ij56ug8kxeyknl0yhLqnNLOUdxtqqo4="
|
||||
},
|
||||
{
|
||||
"pname": "fantomas",
|
||||
"version": "7.0.1",
|
||||
"hash": "sha256-2aGD6Kjh83gmssRqqZ/Uihi7VbNqNUelX4otIfCuhTI="
|
||||
},
|
||||
{
|
||||
"pname": "Fantomas.Core",
|
||||
"version": "6.1.1",
|
||||
"hash": "sha256-FcTLHQFvKkQY/kV08jhhy/St/+FmXpp3epp/R3zUXMA="
|
||||
},
|
||||
{
|
||||
"pname": "Fantomas.FCS",
|
||||
"version": "6.1.1",
|
||||
"hash": "sha256-NuZ8msPEHYA8T3EYREB28F1RcNgUU8V54eg2+UttYxw="
|
||||
},
|
||||
{
|
||||
"pname": "FsCheck",
|
||||
"version": "3.2.0",
|
||||
"hash": "sha256-ksZ4vLgWwyQOzFuK2BczdtDtWWYmedG7UBAg4pYuI8g="
|
||||
},
|
||||
{
|
||||
"pname": "fsharp-analyzers",
|
||||
"version": "0.30.0",
|
||||
"hash": "sha256-7oaSwpHAU1opzpz4szLU/gDaJC/ww9eiFkPu0nr4Mj4="
|
||||
},
|
||||
{
|
||||
"pname": "FSharp.Core",
|
||||
"version": "4.3.4",
|
||||
"hash": "sha256-styyo+6mJy+yxE0NZG/b1hxkAjPOnJfMgd9zWzCJ5uk="
|
||||
},
|
||||
{
|
||||
"pname": "FSharp.Core",
|
||||
"version": "6.0.1",
|
||||
"hash": "sha256-Ehsgt3nCJijpaVuJguC1TPVEKSkJd6PSc07D2ZQSemI="
|
||||
},
|
||||
{
|
||||
"pname": "FSharp.Core",
|
||||
"version": "9.0.202",
|
||||
"hash": "sha256-64Gub0qemmCoMa1tDus6TeTuB1+5sHfE6KD2j4o84mA="
|
||||
},
|
||||
{
|
||||
"pname": "FsUnit",
|
||||
"version": "7.0.1",
|
||||
"hash": "sha256-K85CIdxMeFSHEKZk6heIXp/oFjWAn7dBILKrw49pJUY="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.ApplicationInsights",
|
||||
"version": "2.22.0",
|
||||
"hash": "sha256-mUQ63atpT00r49ca50uZu2YCiLg3yd6r3HzTryqcuEA="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.AspNetCore.App.Ref",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-9jDkWbjw/nd8yqdzVTagCuqr6owJ/DUMi4BlUZT4hWU="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.AspNetCore.App.Runtime.linux-arm64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-JQULJyF0ivLoUU1JaFfK/HHg+/qzpN7V2RR2Cc+WlQ4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.AspNetCore.App.Runtime.linux-x64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-zUsVIpV481vMLAXaLEEUpEMA9/f1HGOnvaQnaWdzlyY="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.AspNetCore.App.Runtime.osx-arm64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-2seqZcz0JeUjkzh3QcGa9TcJ4LUafpFjTRk+Nm8T6T0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.AspNetCore.App.Runtime.osx-x64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-yxLafxiBKkvfkDggPk0P9YZIHBkDJOsFTO7/V9mEHuU="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeCoverage",
|
||||
"version": "17.13.0",
|
||||
"hash": "sha256-GKrIxeyQo5Az1mztfQgea1kGtJwonnNOrXK/0ULfu8o="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NET.Test.Sdk",
|
||||
"version": "17.13.0",
|
||||
"hash": "sha256-sc2wvyV8cGm1FrNP2GGHEI584RCvRPu15erYCsgw5QY="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Host.linux-arm64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-9lC/LYnthYhjkWWz2kkFCvlA5LJOv11jdt59SDnpdy0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Host.linux-x64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-VFRDzx7LJuvI5yzKdGmw/31NYVbwHWPKQvueQt5xc10="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Host.osx-arm64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-DaSWwYACJGolEBuMhzDVCj/rQTdDt061xCVi+gyQnuo="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Host.osx-x64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-FrRny9EI6HKCKQbu6mcLj5w4ooSRrODD4Vj2ZMGnMd4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Ref",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-9LZgVoIFF8qNyUu8kdJrYGLutMF/cL2K82HN2ywwlx8="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Runtime.linux-arm64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-k3rxvUhCEU0pVH8KgEMtkPiSOibn+nBh+0zT2xIfId8="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Runtime.linux-x64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-U8wJ2snSDFqeAgDVLXjnniidC7Cr5aJ1/h/BMSlyu0c="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Runtime.osx-arm64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-UfLcrL2Gj/OLz0s92Oo+OCJeDpZFAcQLPLiSNND8D5Y="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.App.Runtime.osx-x64",
|
||||
"version": "6.0.36",
|
||||
"hash": "sha256-0xIJYFzxdMcnCj3wzkFRQZSnQcPHzPHMzePRIOA3oJs="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.Platforms",
|
||||
"version": "1.1.0",
|
||||
"hash": "sha256-FeM40ktcObQJk4nMYShB61H/E8B7tIKfl9ObJ0IOcCM="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.Platforms",
|
||||
"version": "1.1.1",
|
||||
"hash": "sha256-8hLiUKvy/YirCWlFwzdejD2Db3DaXhHxT7GSZx/znJg="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.Platforms",
|
||||
"version": "2.0.0",
|
||||
"hash": "sha256-IEvBk6wUXSdyCnkj6tHahOJv290tVVT8tyemYcR0Yro="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.Targets",
|
||||
"version": "1.1.0",
|
||||
"hash": "sha256-0AqQ2gMS8iNlYkrD+BxtIg7cXMnr9xZHtKAuN4bjfaQ="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.NETCore.Targets",
|
||||
"version": "1.1.3",
|
||||
"hash": "sha256-WLsf1NuUfRWyr7C7Rl9jiua9jximnVvzy6nk2D2bVRc="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Extensions.Telemetry",
|
||||
"version": "1.5.3",
|
||||
"hash": "sha256-bIXwPSa3jkr2b6xINOqMUs6/uj/r4oVFM7xq3uVIZDU="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Extensions.TrxReport.Abstractions",
|
||||
"version": "1.5.3",
|
||||
"hash": "sha256-IfMRfcyaIKEMRtx326ICKtinDBEfGw/Sv8ZHawJ96Yc="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Extensions.VSTestBridge",
|
||||
"version": "1.5.3",
|
||||
"hash": "sha256-XpM/yFjhLSsuzyDV+xKubs4V1zVVYiV05E0+N4S1h0g="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Platform",
|
||||
"version": "1.5.3",
|
||||
"hash": "sha256-y61Iih6w5D79dmrj2V675mcaeIiHoj1HSa1FRit2BLM="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Testing.Platform.MSBuild",
|
||||
"version": "1.5.3",
|
||||
"hash": "sha256-YspvjE5Jfi587TAfsvfDVJXNrFOkx1B3y1CKV6m7YLY="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.TestPlatform.ObjectModel",
|
||||
"version": "17.12.0",
|
||||
"hash": "sha256-3XBHBSuCxggAIlHXmKNQNlPqMqwFlM952Av6RrLw1/w="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.TestPlatform.ObjectModel",
|
||||
"version": "17.13.0",
|
||||
"hash": "sha256-6S0fjfj8vA+h6dJVNwLi6oZhYDO/I/6hBZaq2VTW+Uk="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.TestPlatform.TestHost",
|
||||
"version": "17.13.0",
|
||||
"hash": "sha256-L/CJzou7dhmShUgXq3aXL3CaLTJll17Q+JY2DBdUUpo="
|
||||
},
|
||||
{
|
||||
"pname": "Myriad.Core",
|
||||
"version": "0.8.3",
|
||||
"hash": "sha256-vBOxfq8QriX/yUtaXN69rEQaY/psRNJWxqATLidrt2g="
|
||||
},
|
||||
{
|
||||
"pname": "Myriad.Sdk",
|
||||
"version": "0.8.3",
|
||||
"hash": "sha256-7O397WKhskKOvE3MkJT37BvxorDWngDR6gTUogtDZ2M="
|
||||
},
|
||||
{
|
||||
"pname": "Nerdbank.GitVersioning",
|
||||
"version": "3.8.38-alpha",
|
||||
"hash": "sha256-gPMrVbjOZxXoofczF/pn6eVkLhjVSJIyQrLO2oljrDc="
|
||||
},
|
||||
{
|
||||
"pname": "NETStandard.Library",
|
||||
"version": "2.0.3",
|
||||
"hash": "sha256-Prh2RPebz/s8AzHb2sPHg3Jl8s31inv9k+Qxd293ybo="
|
||||
},
|
||||
{
|
||||
"pname": "Newtonsoft.Json",
|
||||
"version": "13.0.1",
|
||||
"hash": "sha256-K2tSVW4n4beRPzPu3rlVaBEMdGvWSv/3Q1fxaDh4Mjo="
|
||||
},
|
||||
{
|
||||
"pname": "Newtonsoft.Json",
|
||||
"version": "13.0.3",
|
||||
"hash": "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Common",
|
||||
"version": "6.13.2",
|
||||
"hash": "sha256-ASLa/Jigg5Eop0ZrXPl98RW2rxnJRC7pbbxhuV74hFw="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Configuration",
|
||||
"version": "6.13.2",
|
||||
"hash": "sha256-z8VW1YdRDanyyRTDYRvRkSv/XPR3c/hMM1y8cNNjx0Y="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Frameworks",
|
||||
"version": "6.13.2",
|
||||
"hash": "sha256-caDyc+WgYOo43AUTjtbP0MyvYDb6JweEKDdIul61Cac="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Packaging",
|
||||
"version": "6.13.2",
|
||||
"hash": "sha256-lhO+SFwIYZ4aPHxIGm5ubkkE2a5Ve2xgtroRbNh7hpw="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Protocol",
|
||||
"version": "6.13.2",
|
||||
"hash": "sha256-5lnAHHZjy7A4vgv65AeBAs64mSNpuoUjxW3HnrMpuzY="
|
||||
},
|
||||
{
|
||||
"pname": "NuGet.Versioning",
|
||||
"version": "6.13.2",
|
||||
"hash": "sha256-gmpyBpKnt+GHqgx/2uFKp+J2csbxEAy1E7WdVT117sw="
|
||||
},
|
||||
{
|
||||
"pname": "NUnit",
|
||||
"version": "4.3.2",
|
||||
"hash": "sha256-0RWe8uFoxYp6qhPlDDEghOMcKJgyw2ybvEoAqBLebeE="
|
||||
},
|
||||
{
|
||||
"pname": "NUnit3TestAdapter",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-7jZM4qAbIzne3AcdFfMbvbgogqpxvVe6q2S7Ls8xQy0="
|
||||
},
|
||||
{
|
||||
"pname": "RestEase",
|
||||
"version": "1.6.4",
|
||||
"hash": "sha256-FFmqFwlHhIln46k56Z8KM1G+xuPEh/bceKCQnJcdcdc="
|
||||
},
|
||||
{
|
||||
"pname": "runtime.any.System.Runtime",
|
||||
"version": "4.3.0",
|
||||
"hash": "sha256-qwhNXBaJ1DtDkuRacgHwnZmOZ1u9q7N8j0cWOLYOELM="
|
||||
},
|
||||
{
|
||||
"pname": "runtime.native.System",
|
||||
"version": "4.3.0",
|
||||
"hash": "sha256-ZBZaodnjvLXATWpXXakFgcy6P+gjhshFXmglrL5xD5Y="
|
||||
},
|
||||
{
|
||||
"pname": "runtime.unix.System.Private.Uri",
|
||||
"version": "4.3.0",
|
||||
"hash": "sha256-c5tXWhE/fYbJVl9rXs0uHh3pTsg44YD1dJvyOA0WoMs="
|
||||
},
|
||||
{
|
||||
"pname": "System.Collections.Immutable",
|
||||
"version": "8.0.0",
|
||||
"hash": "sha256-F7OVjKNwpqbUh8lTidbqJWYi476nsq9n+6k0+QVRo3w="
|
||||
},
|
||||
{
|
||||
"pname": "System.Diagnostics.DiagnosticSource",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-6mW3N6FvcdNH/pB58pl+pFSCGWgyaP4hfVtC/SMWDV4="
|
||||
},
|
||||
{
|
||||
"pname": "System.Diagnostics.DiagnosticSource",
|
||||
"version": "7.0.0",
|
||||
"hash": "sha256-9Wk8cHSkjKtqkN6xW7KnXoQVtF/VNbKeBq79WqDesMs="
|
||||
},
|
||||
{
|
||||
"pname": "System.Formats.Asn1",
|
||||
"version": "6.0.0",
|
||||
"hash": "sha256-KaMHgIRBF7Nf3VwOo+gJS1DcD+41cJDPWFh+TDQ8ee8="
|
||||
},
|
||||
{
|
||||
"pname": "System.Formats.Asn1",
|
||||
"version": "8.0.1",
|
||||
"hash": "sha256-may/Wg+esmm1N14kQTG4ESMBi+GQKPp0ZrrBo/o6OXM="
|
||||
},
|
||||
{
|
||||
"pname": "System.IO.Abstractions",
|
||||
"version": "4.2.13",
|
||||
"hash": "sha256-nkC/PiqE6+c1HJ2yTwg3x+qdBh844Z8n3ERWDW8k6Gg="
|
||||
},
|
||||
{
|
||||
"pname": "System.IO.FileSystem.AccessControl",
|
||||
"version": "4.5.0",
|
||||
"hash": "sha256-ck44YBQ0M+2Im5dw0VjBgFD1s0XuY54cujrodjjSBL8="
|
||||
},
|
||||
{
|
||||
"pname": "System.Memory",
|
||||
"version": "4.5.5",
|
||||
"hash": "sha256-EPQ9o1Kin7KzGI5O3U3PUQAZTItSbk9h/i4rViN3WiI="
|
||||
},
|
||||
{
|
||||
"pname": "System.Private.Uri",
|
||||
"version": "4.3.0",
|
||||
"hash": "sha256-fVfgcoP4AVN1E5wHZbKBIOPYZ/xBeSIdsNF+bdukIRM="
|
||||
},
|
||||
{
|
||||
"pname": "System.Reflection.Metadata",
|
||||
"version": "1.6.0",
|
||||
"hash": "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E="
|
||||
},
|
||||
{
|
||||
"pname": "System.Runtime",
|
||||
"version": "4.3.1",
|
||||
"hash": "sha256-R9T68AzS1PJJ7v6ARz9vo88pKL1dWqLOANg4pkQjkA0="
|
||||
},
|
||||
{
|
||||
"pname": "System.Runtime.CompilerServices.Unsafe",
|
||||
"version": "6.0.0",
|
||||
"hash": "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I="
|
||||
},
|
||||
{
|
||||
"pname": "System.Security.AccessControl",
|
||||
"version": "4.5.0",
|
||||
"hash": "sha256-AFsKPb/nTk2/mqH/PYpaoI8PLsiKKimaXf+7Mb5VfPM="
|
||||
},
|
||||
{
|
||||
"pname": "System.Security.Cryptography.Pkcs",
|
||||
"version": "6.0.4",
|
||||
"hash": "sha256-2e0aRybote+OR66bHaNiYpF//4fCiaO3zbR2e9GABUI="
|
||||
},
|
||||
{
|
||||
"pname": "System.Security.Cryptography.ProtectedData",
|
||||
"version": "4.4.0",
|
||||
"hash": "sha256-Ri53QmFX8I8UH0x4PikQ1ZA07ZSnBUXStd5rBfGWFOE="
|
||||
},
|
||||
{
|
||||
"pname": "System.Security.Principal.Windows",
|
||||
"version": "4.5.0",
|
||||
"hash": "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY="
|
||||
},
|
||||
{
|
||||
"pname": "System.Text.Json",
|
||||
"version": "8.0.5",
|
||||
"hash": "sha256-yKxo54w5odWT6nPruUVsaX53oPRe+gKzGvLnnxtwP68="
|
||||
},
|
||||
{
|
||||
"pname": "TypeEquality",
|
||||
"version": "0.3.0",
|
||||
"hash": "sha256-V50xAOzzyUJrY+MYPRxtnqW5MVeATXCes89wPprv1r4="
|
||||
},
|
||||
{
|
||||
"pname": "WoofWare.Whippet.Fantomas",
|
||||
"version": "0.5.1",
|
||||
"hash": "sha256-59CwnOZQAq5ZJoUkd87OiP8KUwx8xYDLMimMMTlKeZA="
|
||||
}
|
||||
]
|
369
nix/deps.nix
369
nix/deps.nix
@@ -1,369 +0,0 @@
|
||||
# This file was automatically generated by passthru.fetch-deps.
|
||||
# Please dont edit it manually, your changes might get overwritten!
|
||||
{fetchNuGet}: [
|
||||
(fetchNuGet {
|
||||
pname = "ApiSurface";
|
||||
version = "4.1.14";
|
||||
hash = "sha256-Ly7XqGeqseQqu+EcBISzVySZvBQ28rj7JUke1qN7Yw8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "fantomas";
|
||||
version = "6.3.16";
|
||||
hash = "sha256-4tRdYf+/Q1iedx+DDuIKVGlIWQdr6erM51VdKzZkhCs=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Fantomas.Core";
|
||||
version = "6.1.1";
|
||||
hash = "sha256-FcTLHQFvKkQY/kV08jhhy/St/+FmXpp3epp/R3zUXMA=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Fantomas.FCS";
|
||||
version = "6.1.1";
|
||||
hash = "sha256-NuZ8msPEHYA8T3EYREB28F1RcNgUU8V54eg2+UttYxw=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FsCheck";
|
||||
version = "2.16.6";
|
||||
hash = "sha256-1hR2SaJTkqBzU3D955MvLNVzkQHkx0Z/QzOXZfzk2Zw=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "fsharp-analyzers";
|
||||
version = "0.28.0";
|
||||
hash = "sha256-BqGk9MzHHA3oRPNfWuANcM1YELsdhzWI+kLF4mUDUx8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "4.2.3";
|
||||
hash = "sha256-yMGMrMUY+4Lwnh9JIbD2/3FBGIFcSK7leGURWaSQsLQ=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "4.3.4";
|
||||
hash = "sha256-styyo+6mJy+yxE0NZG/b1hxkAjPOnJfMgd9zWzCJ5uk=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-7+B+8rsm/dMKvNBty8z5qB+kOxMwUzExy0F04xM88sk=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "5.0.2";
|
||||
hash = "sha256-YOoosLEiszPsOOaNAkWhFGU04JJKDOFVoA/ggrZMN10=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "6.0.1";
|
||||
hash = "sha256-Ehsgt3nCJijpaVuJguC1TPVEKSkJd6PSc07D2ZQSemI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FSharp.Core";
|
||||
version = "9.0.100";
|
||||
hash = "sha256-V1q3CjbRvWZqxpi6cXD/R0F7pyXGGtH83M5Z/ITDrp8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "FsUnit";
|
||||
version = "6.0.1";
|
||||
hash = "sha256-vka/aAgWhDCl5tu+kgO7GtSaHOOvlSaWxG+tExwGXpI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Ref";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-9jDkWbjw/nd8yqdzVTagCuqr6owJ/DUMi4BlUZT4hWU=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-JQULJyF0ivLoUU1JaFfK/HHg+/qzpN7V2RR2Cc+WlQ4=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-zUsVIpV481vMLAXaLEEUpEMA9/f1HGOnvaQnaWdzlyY=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-2seqZcz0JeUjkzh3QcGa9TcJ4LUafpFjTRk+Nm8T6T0=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-yxLafxiBKkvfkDggPk0P9YZIHBkDJOsFTO7/V9mEHuU=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.CodeCoverage";
|
||||
version = "17.12.0";
|
||||
hash = "sha256-lGjifppD0OBMBp28pjUfPipaeXg739n8cPhtHWoo5RE=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NET.Test.Sdk";
|
||||
version = "17.12.0";
|
||||
hash = "sha256-DKFEbhh2wPzahNeHdEoFig8tZh/LEVrFc5+zpT43Btg=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-9lC/LYnthYhjkWWz2kkFCvlA5LJOv11jdt59SDnpdy0=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-VFRDzx7LJuvI5yzKdGmw/31NYVbwHWPKQvueQt5xc10=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-DaSWwYACJGolEBuMhzDVCj/rQTdDt061xCVi+gyQnuo=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-FrRny9EI6HKCKQbu6mcLj5w4ooSRrODD4Vj2ZMGnMd4=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Ref";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-9LZgVoIFF8qNyUu8kdJrYGLutMF/cL2K82HN2ywwlx8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-k3rxvUhCEU0pVH8KgEMtkPiSOibn+nBh+0zT2xIfId8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-U8wJ2snSDFqeAgDVLXjnniidC7Cr5aJ1/h/BMSlyu0c=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-UfLcrL2Gj/OLz0s92Oo+OCJeDpZFAcQLPLiSNND8D5Y=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
||||
version = "6.0.36";
|
||||
hash = "sha256-0xIJYFzxdMcnCj3wzkFRQZSnQcPHzPHMzePRIOA3oJs=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.Platforms";
|
||||
version = "1.1.0";
|
||||
hash = "sha256-FeM40ktcObQJk4nMYShB61H/E8B7tIKfl9ObJ0IOcCM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.Platforms";
|
||||
version = "1.1.1";
|
||||
hash = "sha256-8hLiUKvy/YirCWlFwzdejD2Db3DaXhHxT7GSZx/znJg=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.Platforms";
|
||||
version = "2.0.0";
|
||||
hash = "sha256-IEvBk6wUXSdyCnkj6tHahOJv290tVVT8tyemYcR0Yro=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.Targets";
|
||||
version = "1.1.0";
|
||||
hash = "sha256-0AqQ2gMS8iNlYkrD+BxtIg7cXMnr9xZHtKAuN4bjfaQ=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.NETCore.Targets";
|
||||
version = "1.1.3";
|
||||
hash = "sha256-WLsf1NuUfRWyr7C7Rl9jiua9jximnVvzy6nk2D2bVRc=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.TestPlatform.ObjectModel";
|
||||
version = "17.12.0";
|
||||
hash = "sha256-3XBHBSuCxggAIlHXmKNQNlPqMqwFlM952Av6RrLw1/w=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Microsoft.TestPlatform.TestHost";
|
||||
version = "17.12.0";
|
||||
hash = "sha256-rf8Sh0fQq44Sneuvs64unkkIHg8kOjDGWE35j9iLx5I=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Myriad.Core";
|
||||
version = "0.8.3";
|
||||
hash = "sha256-vBOxfq8QriX/yUtaXN69rEQaY/psRNJWxqATLidrt2g=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Myriad.Sdk";
|
||||
version = "0.8.3";
|
||||
hash = "sha256-7O397WKhskKOvE3MkJT37BvxorDWngDR6gTUogtDZ2M=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Nerdbank.GitVersioning";
|
||||
version = "3.7.112";
|
||||
hash = "sha256-vrItlaH5MpBHa4MI1cQgI11NAe4W3XsxR9DizFE7fus=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NETStandard.Library";
|
||||
version = "2.0.3";
|
||||
hash = "sha256-Prh2RPebz/s8AzHb2sPHg3Jl8s31inv9k+Qxd293ybo=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Newtonsoft.Json";
|
||||
version = "13.0.1";
|
||||
hash = "sha256-K2tSVW4n4beRPzPu3rlVaBEMdGvWSv/3Q1fxaDh4Mjo=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "Newtonsoft.Json";
|
||||
version = "13.0.3";
|
||||
hash = "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Common";
|
||||
version = "6.12.1";
|
||||
hash = "sha256-k6JAFqHFinTakwNuW666aXYPhR7TpI/rb+KbHm1S2TM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Configuration";
|
||||
version = "6.12.1";
|
||||
hash = "sha256-e/4lvyl7o7g4aWTAtr9S2yiGgk7V0E9p6DXpsy7GgVw=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Frameworks";
|
||||
version = "6.12.1";
|
||||
hash = "sha256-GGpkbas+PNLx35vvr3nyAVz5lY/aeoMx6qjmT368Lpg=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Packaging";
|
||||
version = "6.12.1";
|
||||
hash = "sha256-3h8Nmjpt383+dCg9GJ1BJ26UirwEQsWCPcTiT0+wGeI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Protocol";
|
||||
version = "6.12.1";
|
||||
hash = "sha256-l+CHnAcit6Y9OjBxereRP5JzOuWbuZZQYkFOKsUkdQ8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NuGet.Versioning";
|
||||
version = "6.12.1";
|
||||
hash = "sha256-f/ejCuzCAwKs4N4Ec6yf2RovrhBT0nj0hRDP+03/Iy4=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NUnit";
|
||||
version = "4.0.1";
|
||||
hash = "sha256-jd1CD5nHVXkpvBNpVDJcJyfTggCHLyDBySVSvtrA8Uk=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NUnit";
|
||||
version = "4.3.0";
|
||||
hash = "sha256-dL8+6yL7nwgQKZR3wo2hAOUt3d2EFN10GJH1LzY89I8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "NUnit3TestAdapter";
|
||||
version = "4.6.0";
|
||||
hash = "sha256-9Yav2fYhC4w0OgsyUwU4/5rDy4FVDTpKnWHuwl/uKJQ=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "RestEase";
|
||||
version = "1.6.4";
|
||||
hash = "sha256-FFmqFwlHhIln46k56Z8KM1G+xuPEh/bceKCQnJcdcdc=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "runtime.any.System.Runtime";
|
||||
version = "4.3.0";
|
||||
hash = "sha256-qwhNXBaJ1DtDkuRacgHwnZmOZ1u9q7N8j0cWOLYOELM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "runtime.native.System";
|
||||
version = "4.3.0";
|
||||
hash = "sha256-ZBZaodnjvLXATWpXXakFgcy6P+gjhshFXmglrL5xD5Y=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "runtime.unix.System.Private.Uri";
|
||||
version = "4.3.0";
|
||||
hash = "sha256-c5tXWhE/fYbJVl9rXs0uHh3pTsg44YD1dJvyOA0WoMs=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Diagnostics.DiagnosticSource";
|
||||
version = "7.0.0";
|
||||
hash = "sha256-9Wk8cHSkjKtqkN6xW7KnXoQVtF/VNbKeBq79WqDesMs=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Formats.Asn1";
|
||||
version = "6.0.0";
|
||||
hash = "sha256-KaMHgIRBF7Nf3VwOo+gJS1DcD+41cJDPWFh+TDQ8ee8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Formats.Asn1";
|
||||
version = "8.0.1";
|
||||
hash = "sha256-may/Wg+esmm1N14kQTG4ESMBi+GQKPp0ZrrBo/o6OXM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.IO.Abstractions";
|
||||
version = "4.2.13";
|
||||
hash = "sha256-nkC/PiqE6+c1HJ2yTwg3x+qdBh844Z8n3ERWDW8k6Gg=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.IO.FileSystem.AccessControl";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-ck44YBQ0M+2Im5dw0VjBgFD1s0XuY54cujrodjjSBL8=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Memory";
|
||||
version = "4.5.5";
|
||||
hash = "sha256-EPQ9o1Kin7KzGI5O3U3PUQAZTItSbk9h/i4rViN3WiI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Private.Uri";
|
||||
version = "4.3.0";
|
||||
hash = "sha256-fVfgcoP4AVN1E5wHZbKBIOPYZ/xBeSIdsNF+bdukIRM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Reflection.Metadata";
|
||||
version = "1.6.0";
|
||||
hash = "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Runtime";
|
||||
version = "4.3.1";
|
||||
hash = "sha256-R9T68AzS1PJJ7v6ARz9vo88pKL1dWqLOANg4pkQjkA0=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Runtime.CompilerServices.Unsafe";
|
||||
version = "6.0.0";
|
||||
hash = "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.AccessControl";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-AFsKPb/nTk2/mqH/PYpaoI8PLsiKKimaXf+7Mb5VfPM=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Cryptography.Pkcs";
|
||||
version = "6.0.4";
|
||||
hash = "sha256-2e0aRybote+OR66bHaNiYpF//4fCiaO3zbR2e9GABUI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Cryptography.ProtectedData";
|
||||
version = "4.4.0";
|
||||
hash = "sha256-Ri53QmFX8I8UH0x4PikQ1ZA07ZSnBUXStd5rBfGWFOE=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Security.Principal.Windows";
|
||||
version = "4.5.0";
|
||||
hash = "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Text.Encodings.Web";
|
||||
version = "8.0.0";
|
||||
hash = "sha256-IUQkQkV9po1LC0QsqrilqwNzPvnc+4eVvq+hCvq8fvE=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "System.Text.Json";
|
||||
version = "8.0.4";
|
||||
hash = "sha256-g5oT7fbXxQ9Iah1nMCr4UUX/a2l+EVjJyTrw3FTbIaI=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "TypeEquality";
|
||||
version = "0.3.0";
|
||||
hash = "sha256-V50xAOzzyUJrY+MYPRxtnqW5MVeATXCes89wPprv1r4=";
|
||||
})
|
||||
(fetchNuGet {
|
||||
pname = "WoofWare.Whippet.Fantomas";
|
||||
version = "0.3.1";
|
||||
hash = "sha256-i5oiqcrxzM90Ocuq5MIu2Ha5lV0aYu5nCvuwmFqp6NA=";
|
||||
})
|
||||
]
|
Reference in New Issue
Block a user