mirror of
				https://github.com/Smaug123/WoofWare.Myriad
				synced 2025-10-31 00:29:00 +00:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			WoofWare.M
			...
			f2922a37a4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f2922a37a4 | ||
|  | 030d8ffa12 | ||
|  | d86bd743af | ||
|  | dff2431bc8 | 
| @@ -3,13 +3,13 @@ | |||||||
|   "isRoot": true, |   "isRoot": true, | ||||||
|   "tools": { |   "tools": { | ||||||
|     "fantomas": { |     "fantomas": { | ||||||
|       "version": "6.3.7", |       "version": "6.3.0-alpha-007", | ||||||
|       "commands": [ |       "commands": [ | ||||||
|         "fantomas" |         "fantomas" | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "fsharp-analyzers": { |     "fsharp-analyzers": { | ||||||
|       "version": "0.26.0", |       "version": "0.24.0", | ||||||
|       "commands": [ |       "commands": [ | ||||||
|         "fsharp-analyzers" |         "fsharp-analyzers" | ||||||
|       ] |       ] | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ root=true | |||||||
|  |  | ||||||
| [*] | [*] | ||||||
| charset=utf-8 | charset=utf-8 | ||||||
|  | end_of_line=crlf | ||||||
| trim_trailing_whitespace=true | trim_trailing_whitespace=true | ||||||
| insert_final_newline=true | insert_final_newline=true | ||||||
| indent_style=space | indent_style=space | ||||||
|   | |||||||
							
								
								
									
										85
									
								
								.github/workflows/dotnet.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								.github/workflows/dotnet.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,3 @@ | |||||||
| # yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-workflow.json |  | ||||||
| name: .NET | name: .NET | ||||||
|  |  | ||||||
| on: | on: | ||||||
| @@ -29,7 +28,7 @@ jobs: | |||||||
|       with: |       with: | ||||||
|         fetch-depth: 0 # so that NerdBank.GitVersioning has access to history |         fetch-depth: 0 # so that NerdBank.GitVersioning has access to history | ||||||
|     - name: Install Nix |     - name: Install Nix | ||||||
|       uses: cachix/install-nix-action@V27 |       uses: cachix/install-nix-action@v25 | ||||||
|       with: |       with: | ||||||
|         extra_nix_config: | |         extra_nix_config: | | ||||||
|           access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |           access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -50,7 +49,7 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           fetch-depth: 0 # so that NerdBank.GitVersioning has access to history |           fetch-depth: 0 # so that NerdBank.GitVersioning has access to history | ||||||
|       - name: Install Nix |       - name: Install Nix | ||||||
|         uses: cachix/install-nix-action@V27 |         uses: cachix/install-nix-action@v25 | ||||||
|         with: |         with: | ||||||
|           extra_nix_config: | |           extra_nix_config: | | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -59,7 +58,7 @@ jobs: | |||||||
|       - name: Build project |       - name: Build project | ||||||
|         run: nix develop --command dotnet build ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj |         run: nix develop --command dotnet build ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj | ||||||
|       - name: Run analyzers |       - name: Run analyzers | ||||||
|         run: nix run .#fsharp-analyzers -- --project ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj --analyzers-path ./.analyzerpackages/g-research.fsharp.analyzers/*/ --verbosity detailed --report ./analysis.sarif --treat-as-error GRA-STRING-001 GRA-STRING-002 GRA-STRING-003 GRA-UNIONCASE-001 GRA-INTERPOLATED-001 GRA-TYPE-ANNOTATE-001 GRA-VIRTUALCALL-001 GRA-IMMUTABLECOLLECTIONEQUALITY-001 GRA-JSONOPTS-001 GRA-LOGARGFUNCFULLAPP-001 GRA-DISPBEFOREASYNC-001 --exclude-analyzers PartialAppAnalyzer |         run: nix run .#fsharp-analyzers -- --project ./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj --analyzers-path ./.analyzerpackages/g-research.fsharp.analyzers/0.8.0/ --verbosity detailed --report ./analysis.sarif --treat-as-error GRA-STRING-001 GRA-STRING-002 GRA-STRING-003 GRA-UNIONCASE-001 GRA-INTERPOLATED-001 GRA-TYPE-ANNOTATE-001 GRA-VIRTUALCALL-001 GRA-IMMUTABLECOLLECTIONEQUALITY-001 GRA-JSONOPTS-001 GRA-LOGARGFUNCFULLAPP-001 GRA-DISPBEFOREASYNC-001 --exclude-analyzers PartialAppAnalyzer | ||||||
|  |  | ||||||
|   build-nix: |   build-nix: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
| @@ -67,7 +66,7 @@ jobs: | |||||||
|       - name: Checkout |       - name: Checkout | ||||||
|         uses: actions/checkout@v4 |         uses: actions/checkout@v4 | ||||||
|       - name: Install Nix |       - name: Install Nix | ||||||
|         uses: cachix/install-nix-action@V27 |         uses: cachix/install-nix-action@v25 | ||||||
|         with: |         with: | ||||||
|           extra_nix_config: | |           extra_nix_config: | | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -80,41 +79,20 @@ jobs: | |||||||
|       - name: Checkout |       - name: Checkout | ||||||
|         uses: actions/checkout@v4 |         uses: actions/checkout@v4 | ||||||
|       - name: Install Nix |       - name: Install Nix | ||||||
|         uses: cachix/install-nix-action@V27 |         uses: cachix/install-nix-action@v25 | ||||||
|         with: |         with: | ||||||
|           extra_nix_config: | |           extra_nix_config: | | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
|       - name: Run Fantomas |       - name: Run Fantomas | ||||||
|         run: nix run .#fantomas -- --check . |         run: nix run .#fantomas -- --check . | ||||||
|  |  | ||||||
|   check-accurate-generations: |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     steps: |  | ||||||
|       - name: Checkout |  | ||||||
|         uses: actions/checkout@v4 |  | ||||||
|         with: |  | ||||||
|           fetch-depth: 0 # so that NerdBank.GitVersioning has access to history |  | ||||||
|       - name: Install Nix |  | ||||||
|         uses: cachix/install-nix-action@V27 |  | ||||||
|         with: |  | ||||||
|           extra_nix_config: | |  | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |  | ||||||
|       - name: Whitespace change |  | ||||||
|         run: "echo ' ' >> ConsumePlugin/List.fs" |  | ||||||
|       - name: Generate code |  | ||||||
|         run: nix develop --command dotnet build |  | ||||||
|       - name: Run Fantomas |  | ||||||
|         run: nix run .#fantomas -- . |  | ||||||
|       - name: Verify there is no diff |  | ||||||
|         run: git diff --name-only --no-color --exit-code |  | ||||||
|  |  | ||||||
|   check-nix-format: |   check-nix-format: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - name: Checkout |       - name: Checkout | ||||||
|         uses: actions/checkout@v4 |         uses: actions/checkout@v4 | ||||||
|       - name: Install Nix |       - name: Install Nix | ||||||
|         uses: cachix/install-nix-action@V27 |         uses: cachix/install-nix-action@v25 | ||||||
|         with: |         with: | ||||||
|           extra_nix_config: | |           extra_nix_config: | | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -127,7 +105,7 @@ jobs: | |||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@master |       - uses: actions/checkout@master | ||||||
|       - name: Install Nix |       - name: Install Nix | ||||||
|         uses: cachix/install-nix-action@V27 |         uses: cachix/install-nix-action@v25 | ||||||
|         with: |         with: | ||||||
|           extra_nix_config: | |           extra_nix_config: | | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -140,7 +118,7 @@ jobs: | |||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@master |       - uses: actions/checkout@master | ||||||
|       - name: Install Nix |       - name: Install Nix | ||||||
|         uses: cachix/install-nix-action@V27 |         uses: cachix/install-nix-action@v25 | ||||||
|         with: |         with: | ||||||
|           extra_nix_config: | |           extra_nix_config: | | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -154,7 +132,7 @@ jobs: | |||||||
|       with: |       with: | ||||||
|         fetch-depth: 0 # so that NerdBank.GitVersioning has access to history |         fetch-depth: 0 # so that NerdBank.GitVersioning has access to history | ||||||
|     - name: Install Nix |     - name: Install Nix | ||||||
|       uses: cachix/install-nix-action@V27 |       uses: cachix/install-nix-action@v25 | ||||||
|       with: |       with: | ||||||
|         extra_nix_config: | |         extra_nix_config: | | ||||||
|           access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |           access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -196,27 +174,8 @@ jobs: | |||||||
|         # Verify that there is exactly one nupkg in the artifact that would be NuGet published |         # Verify that there is exactly one nupkg in the artifact that would be NuGet published | ||||||
|         run: if [[ $(find packed-attribute -maxdepth 1 -name 'WoofWare.Myriad.Plugins.Attributes.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi |         run: if [[ $(find packed-attribute -maxdepth 1 -name 'WoofWare.Myriad.Plugins.Attributes.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi | ||||||
|  |  | ||||||
|   github-release-plugin-dry-run: |  | ||||||
|     needs: [nuget-pack] |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@v4 |  | ||||||
|       - name: Download NuGet artifact (plugin) |  | ||||||
|         uses: actions/download-artifact@v4 |  | ||||||
|         with: |  | ||||||
|           name: nuget-package-plugin |  | ||||||
|       - name: Download NuGet artifact (attribute) |  | ||||||
|         uses: actions/download-artifact@v4 |  | ||||||
|         with: |  | ||||||
|           name: nuget-package-attribute |  | ||||||
|       - name: Tag and release plugin |  | ||||||
|         env: |  | ||||||
|           DRY_RUN: 1 |  | ||||||
|           GITHUB_TOKEN: mock-token |  | ||||||
|         run: sh .github/workflows/tag.sh |  | ||||||
|  |  | ||||||
|   all-required-checks-complete: |   all-required-checks-complete: | ||||||
|     needs: [check-dotnet-format, check-nix-format, 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, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack] | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - run: echo "All required checks complete." |       - run: echo "All required checks complete." | ||||||
| @@ -229,7 +188,7 @@ jobs: | |||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v4 |       - uses: actions/checkout@v4 | ||||||
|       - name: Install Nix |       - name: Install Nix | ||||||
|         uses: cachix/install-nix-action@V27 |         uses: cachix/install-nix-action@v25 | ||||||
|         with: |         with: | ||||||
|           extra_nix_config: | |           extra_nix_config: | | ||||||
|             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} |             access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} | ||||||
| @@ -247,25 +206,3 @@ jobs: | |||||||
|           path: packed-attribute |           path: packed-attribute | ||||||
|       - name: Publish to NuGet (attribute) |       - name: Publish to NuGet (attribute) | ||||||
|         run: nix develop --command dotnet nuget push "packed-attribute/WoofWare.Myriad.Plugins.Attributes.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate |         run: nix develop --command dotnet nuget push "packed-attribute/WoofWare.Myriad.Plugins.Attributes.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate | ||||||
|  |  | ||||||
|   github-release-plugin: |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }} |  | ||||||
|     needs: [all-required-checks-complete] |  | ||||||
|     environment: main-deploy |  | ||||||
|     permissions: |  | ||||||
|       contents: write |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@v4 |  | ||||||
|       - name: Download NuGet artifact (plugin) |  | ||||||
|         uses: actions/download-artifact@v4 |  | ||||||
|         with: |  | ||||||
|           name: nuget-package-plugin |  | ||||||
|       - name: Download NuGet artifact (attribute) |  | ||||||
|         uses: actions/download-artifact@v4 |  | ||||||
|         with: |  | ||||||
|           name: nuget-package-attribute |  | ||||||
|       - name: Tag and release plugin |  | ||||||
|         env: |  | ||||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |  | ||||||
|         run: sh .github/workflows/tag.sh |  | ||||||
|   | |||||||
							
								
								
									
										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 |  | ||||||
							
								
								
									
										23
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,27 +1,6 @@ | |||||||
| Notable changes are recorded here. | Notable changes are recorded here. | ||||||
|  |  | ||||||
| # WoofWare.Myriad.Plugins 2.1.33 | # WoofWare.Myriad.Plugins 1.4 -> 2.0 | ||||||
|  |  | ||||||
| `JsonParse` can now deserialize the discriminated unions which `JsonSerialize` wrote out. |  | ||||||
|  |  | ||||||
| # WoofWare.Myriad.Plugins 2.1.32, WoofWare.Myriad.Plugins.Attributes 3.1.4 |  | ||||||
|  |  | ||||||
| `JsonSerialize` can now serialize many discriminated unions. |  | ||||||
| (This operation is inherently opinionated, because JSON does not model discriminated unions.) |  | ||||||
|  |  | ||||||
| # WoofWare.Myriad.Plugins 2.1.20, WoofWare.Myriad.Plugins.Attributes 3.0.1 |  | ||||||
|  |  | ||||||
| We now bundle copies of the RestEase attributes in `WoofWare.Myriad.Plugins.Attributes`, in case you don't want to take a dependency on RestEase. |  | ||||||
|  |  | ||||||
| # WoofWare.Myriad.Plugins 2.1.15 |  | ||||||
|  |  | ||||||
| The `GenerateMock` generator now permits a limited amount of inheritance in the record we're mocking out (specifically, `IDisposable`). |  | ||||||
|  |  | ||||||
| # WoofWare.Myriad.Plugins 2.1.8 |  | ||||||
|  |  | ||||||
| No change to the packages, but this is when we started creating and tagging GitHub releases, which are a better source of truth than this file. |  | ||||||
|  |  | ||||||
| # WoofWare.Myriad.Plugins 2.0 |  | ||||||
|  |  | ||||||
| This transition split the attributes (e.g. `[<JsonParseAttribute>]`) into their own assembly, WoofWare.Myriad.Plugins.Attributes. | This transition split the attributes (e.g. `[<JsonParseAttribute>]`) into their own assembly, WoofWare.Myriad.Plugins.Attributes. | ||||||
| The new assembly has minimal dependencies, so you may safely use it from your own code. | The new assembly has minimal dependencies, so you may safely use it from your own code. | ||||||
|   | |||||||
| @@ -92,13 +92,13 @@ module TreeCata = | |||||||
|                 let arg0_0 = treeStack.[treeStack.Count - 1] |                 let arg0_0 = treeStack.[treeStack.Count - 1] | ||||||
|                 treeStack.RemoveAt (treeStack.Count - 1) |                 treeStack.RemoveAt (treeStack.Count - 1) | ||||||
|                 cata.TreeBuilder.Parent arg0_0 |> treeBuilderStack.Add |                 cata.TreeBuilder.Parent arg0_0 |> treeBuilderStack.Add | ||||||
|             | Instruction.Tree_Pair arg2_0 -> |             | Instruction.Tree_Pair (arg2_0) -> | ||||||
|                 let arg0_0 = treeStack.[treeStack.Count - 1] |                 let arg0_0 = treeStack.[treeStack.Count - 1] | ||||||
|                 treeStack.RemoveAt (treeStack.Count - 1) |                 treeStack.RemoveAt (treeStack.Count - 1) | ||||||
|                 let arg1_0 = treeStack.[treeStack.Count - 1] |                 let arg1_0 = treeStack.[treeStack.Count - 1] | ||||||
|                 treeStack.RemoveAt (treeStack.Count - 1) |                 treeStack.RemoveAt (treeStack.Count - 1) | ||||||
|                 cata.Tree.Pair arg0_0 arg1_0 arg2_0 |> treeStack.Add |                 cata.Tree.Pair arg0_0 arg1_0 arg2_0 |> treeStack.Add | ||||||
|             | Instruction.Tree_Sequential arg0_0 -> |             | Instruction.Tree_Sequential (arg0_0) -> | ||||||
|                 let arg0_0_len = arg0_0 |                 let arg0_0_len = arg0_0 | ||||||
|  |  | ||||||
|                 let arg0_0 = |                 let arg0_0 = | ||||||
|   | |||||||
| @@ -129,7 +129,7 @@ module GiftCata = | |||||||
|                 | Gift.WithACard (arg0_0, message) -> |                 | Gift.WithACard (arg0_0, message) -> | ||||||
|                     instructions.Add (Instruction.Gift_WithACard (message)) |                     instructions.Add (Instruction.Gift_WithACard (message)) | ||||||
|                     instructions.Add (Instruction.Process__Gift arg0_0) |                     instructions.Add (Instruction.Process__Gift arg0_0) | ||||||
|             | Instruction.Gift_Wrapped arg1_0 -> |             | Instruction.Gift_Wrapped (arg1_0) -> | ||||||
|                 let arg0_0 = giftStack.[giftStack.Count - 1] |                 let arg0_0 = giftStack.[giftStack.Count - 1] | ||||||
|                 giftStack.RemoveAt (giftStack.Count - 1) |                 giftStack.RemoveAt (giftStack.Count - 1) | ||||||
|                 cata.Gift.Wrapped arg0_0 arg1_0 |> giftStack.Add |                 cata.Gift.Wrapped arg0_0 arg1_0 |> giftStack.Add | ||||||
| @@ -137,7 +137,7 @@ module GiftCata = | |||||||
|                 let arg0_0 = giftStack.[giftStack.Count - 1] |                 let arg0_0 = giftStack.[giftStack.Count - 1] | ||||||
|                 giftStack.RemoveAt (giftStack.Count - 1) |                 giftStack.RemoveAt (giftStack.Count - 1) | ||||||
|                 cata.Gift.Boxed arg0_0 |> giftStack.Add |                 cata.Gift.Boxed arg0_0 |> giftStack.Add | ||||||
|             | Instruction.Gift_WithACard message -> |             | Instruction.Gift_WithACard (message) -> | ||||||
|                 let arg0_0 = giftStack.[giftStack.Count - 1] |                 let arg0_0 = giftStack.[giftStack.Count - 1] | ||||||
|                 giftStack.RemoveAt (giftStack.Count - 1) |                 giftStack.RemoveAt (giftStack.Count - 1) | ||||||
|                 cata.Gift.WithACard arg0_0 message |> giftStack.Add |                 cata.Gift.WithACard arg0_0 message |> giftStack.Add | ||||||
|   | |||||||
| @@ -8,11 +8,12 @@ | |||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the InnerType type | /// Module containing JSON parsing methods for the InnerType type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module InnerType = | module InnerType = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerType = | ||||||
|         let arg_0 = |         let Thing = | ||||||
|             (match node.[(Literals.something)] with |             (match node.[(Literals.something)] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -25,16 +26,17 @@ module InnerType = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Thing = arg_0 |             Thing = Thing | ||||||
|         } |         } | ||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the JsonRecordType type | /// Module containing JSON parsing methods for the JsonRecordType type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module JsonRecordType = | module JsonRecordType = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordType = | ||||||
|         let arg_5 = |         let F = | ||||||
|             (match node.["f"] with |             (match node.["f"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -47,7 +49,7 @@ module JsonRecordType = | |||||||
|             |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) |             |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) | ||||||
|             |> Array.ofSeq |             |> Array.ofSeq | ||||||
|  |  | ||||||
|         let arg_4 = |         let E = | ||||||
|             (match node.["e"] with |             (match node.["e"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -60,7 +62,7 @@ module JsonRecordType = | |||||||
|             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) |             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) | ||||||
|             |> Array.ofSeq |             |> Array.ofSeq | ||||||
|  |  | ||||||
|         let arg_3 = |         let D = | ||||||
|             InnerType.jsonParse ( |             InnerType.jsonParse ( | ||||||
|                 match node.["d"] with |                 match node.["d"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -72,7 +74,7 @@ module JsonRecordType = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_2 = |         let C = | ||||||
|             (match node.["hi"] with |             (match node.["hi"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -85,7 +87,7 @@ module JsonRecordType = | |||||||
|             |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) |             |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) | ||||||
|             |> List.ofSeq |             |> List.ofSeq | ||||||
|  |  | ||||||
|         let arg_1 = |         let B = | ||||||
|             (match node.["another-thing"] with |             (match node.["another-thing"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -97,7 +99,7 @@ module JsonRecordType = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let A = | ||||||
|             (match node.["a"] with |             (match node.["a"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -110,12 +112,12 @@ module JsonRecordType = | |||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             A = arg_0 |             A = A | ||||||
|             B = arg_1 |             B = B | ||||||
|             C = arg_2 |             C = C | ||||||
|             D = arg_3 |             D = D | ||||||
|             E = arg_4 |             E = E | ||||||
|             F = arg_5 |             F = F | ||||||
|         } |         } | ||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| @@ -127,230 +129,24 @@ module ToGetExtensionMethodJsonParseExtension = | |||||||
|  |  | ||||||
|         /// Parse from a JSON node. |         /// Parse from a JSON node. | ||||||
|         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : ToGetExtensionMethod = |         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : ToGetExtensionMethod = | ||||||
|             let arg_20 = System.Numerics.BigInteger.Parse (node.["whiskey"].ToJsonString ()) |             let Sailor = | ||||||
|  |                 (match node.["sailor"] with | ||||||
|             let arg_19 = |  | ||||||
|                 (match node.["victor"] with |  | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |                          System.Collections.Generic.KeyNotFoundException ( | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("victor") |                              sprintf "Required key '%s' not found on JSON object" ("sailor") | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Char> () |  | ||||||
|  |  | ||||||
|             let arg_18 = |  | ||||||
|                 (match node.["uniform"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("uniform") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Decimal> () |  | ||||||
|  |  | ||||||
|             let arg_17 = |  | ||||||
|                 (match node.["tango"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("tango") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.SByte> () |  | ||||||
|  |  | ||||||
|             let arg_16 = |  | ||||||
|                 (match node.["quebec"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("quebec") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Byte> () |  | ||||||
|  |  | ||||||
|             let arg_15 = |  | ||||||
|                 (match node.["papa"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("papa") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Byte> () |  | ||||||
|  |  | ||||||
|             let arg_14 = |  | ||||||
|                 (match node.["oscar"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("oscar") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.SByte> () |  | ||||||
|  |  | ||||||
|             let arg_13 = |  | ||||||
|                 (match node.["november"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("november") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.UInt16> () |  | ||||||
|  |  | ||||||
|             let arg_12 = |  | ||||||
|                 (match node.["mike"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("mike") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Int16> () |  | ||||||
|  |  | ||||||
|             let arg_11 = |  | ||||||
|                 (match node.["lima"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("lima") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.UInt32> () |  | ||||||
|  |  | ||||||
|             let arg_10 = |  | ||||||
|                 (match node.["kilo"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("kilo") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Int32> () |  | ||||||
|  |  | ||||||
|             let arg_9 = |  | ||||||
|                 (match node.["juliette"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("juliette") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.UInt32> () |  | ||||||
|  |  | ||||||
|             let arg_8 = |  | ||||||
|                 (match node.["india"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("india") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<int> () |  | ||||||
|  |  | ||||||
|             let arg_7 = |  | ||||||
|                 (match node.["hotel"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("hotel") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.UInt64> () |  | ||||||
|  |  | ||||||
|             let arg_6 = |  | ||||||
|                 (match node.["golf"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("golf") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Int64> () |  | ||||||
|  |  | ||||||
|             let arg_5 = |  | ||||||
|                 (match node.["foxtrot"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("foxtrot") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Double> () |  | ||||||
|  |  | ||||||
|             let arg_4 = |  | ||||||
|                 (match node.["echo"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("echo") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Single> () |  | ||||||
|  |  | ||||||
|             let arg_3 = |  | ||||||
|                 (match node.["delta"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("delta") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                     .AsValue() |  | ||||||
|                     .GetValue<System.Single> () |  | ||||||
|  |  | ||||||
|             let arg_2 = |  | ||||||
|                 (match node.["charlie"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("charlie") |  | ||||||
|                          ) |                          ) | ||||||
|                      ) |                      ) | ||||||
|                  | v -> v) |                  | v -> v) | ||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<float> () |                     .GetValue<float> () | ||||||
|  |  | ||||||
|             let arg_1 = |             let Soldier = | ||||||
|                 (match node.["bravo"] with |                 (match node.["soldier"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |                          System.Collections.Generic.KeyNotFoundException ( | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("bravo") |                              sprintf "Required key '%s' not found on JSON object" ("soldier") | ||||||
|                          ) |                          ) | ||||||
|                      ) |                      ) | ||||||
|                  | v -> v) |                  | v -> v) | ||||||
| @@ -358,12 +154,24 @@ module ToGetExtensionMethodJsonParseExtension = | |||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|                 |> System.Uri |                 |> System.Uri | ||||||
|  |  | ||||||
|             let arg_0 = |             let Tailor = | ||||||
|                 (match node.["alpha"] with |                 (match node.["tailor"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |                          System.Collections.Generic.KeyNotFoundException ( | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("alpha") |                              sprintf "Required key '%s' not found on JSON object" ("tailor") | ||||||
|  |                          ) | ||||||
|  |                      ) | ||||||
|  |                  | v -> v) | ||||||
|  |                     .AsValue() | ||||||
|  |                     .GetValue<int> () | ||||||
|  |  | ||||||
|  |             let Tinker = | ||||||
|  |                 (match node.["tinker"] with | ||||||
|  |                  | null -> | ||||||
|  |                      raise ( | ||||||
|  |                          System.Collections.Generic.KeyNotFoundException ( | ||||||
|  |                              sprintf "Required key '%s' not found on JSON object" ("tinker") | ||||||
|                          ) |                          ) | ||||||
|                      ) |                      ) | ||||||
|                  | v -> v) |                  | v -> v) | ||||||
| @@ -371,25 +179,8 @@ module ToGetExtensionMethodJsonParseExtension = | |||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             { |             { | ||||||
|                 Alpha = arg_0 |                 Tinker = Tinker | ||||||
|                 Bravo = arg_1 |                 Tailor = Tailor | ||||||
|                 Charlie = arg_2 |                 Soldier = Soldier | ||||||
|                 Delta = arg_3 |                 Sailor = Sailor | ||||||
|                 Echo = arg_4 |  | ||||||
|                 Foxtrot = arg_5 |  | ||||||
|                 Golf = arg_6 |  | ||||||
|                 Hotel = arg_7 |  | ||||||
|                 India = arg_8 |  | ||||||
|                 Juliette = arg_9 |  | ||||||
|                 Kilo = arg_10 |  | ||||||
|                 Lima = arg_11 |  | ||||||
|                 Mike = arg_12 |  | ||||||
|                 November = arg_13 |  | ||||||
|                 Oscar = arg_14 |  | ||||||
|                 Papa = arg_15 |  | ||||||
|                 Quebec = arg_16 |  | ||||||
|                 Tango = arg_17 |  | ||||||
|                 Uniform = arg_18 |  | ||||||
|                 Victor = arg_19 |  | ||||||
|                 Whiskey = arg_20 |  | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -5,7 +5,6 @@ | |||||||
|  |  | ||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| /// Mock record type for an interface | /// Mock record type for an interface | ||||||
| @@ -19,18 +18,17 @@ type internal PublicTypeMock = | |||||||
|     /// An implementation where every method throws. |     /// An implementation where every method throws. | ||||||
|     static member Empty : PublicTypeMock = |     static member Empty : PublicTypeMock = | ||||||
|         { |         { | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem3 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     interface IPublicType with |     interface IPublicType with | ||||||
|         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) |         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) | ||||||
|         member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) |         member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0) | ||||||
|         member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1) |         member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1) | ||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| /// Mock record type for an interface | /// Mock record type for an interface | ||||||
| @@ -44,18 +42,17 @@ type public PublicTypeInternalFalseMock = | |||||||
|     /// An implementation where every method throws. |     /// An implementation where every method throws. | ||||||
|     static member Empty : PublicTypeInternalFalseMock = |     static member Empty : PublicTypeInternalFalseMock = | ||||||
|         { |         { | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem3 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     interface IPublicTypeInternalFalse with |     interface IPublicTypeInternalFalse with | ||||||
|         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) |         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) | ||||||
|         member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) |         member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0) | ||||||
|         member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1) |         member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1) | ||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| /// Mock record type for an interface | /// Mock record type for an interface | ||||||
| @@ -68,16 +65,15 @@ type internal InternalTypeMock = | |||||||
|     /// An implementation where every method throws. |     /// An implementation where every method throws. | ||||||
|     static member Empty : InternalTypeMock = |     static member Empty : InternalTypeMock = | ||||||
|         { |         { | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     interface InternalType with |     interface InternalType with | ||||||
|         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) |         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) | ||||||
|         member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) |         member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0) | ||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| /// Mock record type for an interface | /// Mock record type for an interface | ||||||
| @@ -90,16 +86,15 @@ type private PrivateTypeMock = | |||||||
|     /// An implementation where every method throws. |     /// An implementation where every method throws. | ||||||
|     static member Empty : PrivateTypeMock = |     static member Empty : PrivateTypeMock = | ||||||
|         { |         { | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     interface PrivateType with |     interface PrivateType with | ||||||
|         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) |         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) | ||||||
|         member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) |         member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0) | ||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| /// Mock record type for an interface | /// Mock record type for an interface | ||||||
| @@ -112,16 +107,15 @@ type private PrivateTypeInternalFalseMock = | |||||||
|     /// An implementation where every method throws. |     /// An implementation where every method throws. | ||||||
|     static member Empty : PrivateTypeInternalFalseMock = |     static member Empty : PrivateTypeInternalFalseMock = | ||||||
|         { |         { | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     interface PrivateTypeInternalFalse with |     interface PrivateTypeInternalFalse with | ||||||
|         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) |         member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1) | ||||||
|         member this.Mem2 arg_0_0 = this.Mem2 (arg_0_0) |         member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0) | ||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| /// Mock record type for an interface | /// Mock record type for an interface | ||||||
| @@ -133,14 +127,13 @@ type internal VeryPublicTypeMock<'a, 'b> = | |||||||
|     /// An implementation where every method throws. |     /// An implementation where every method throws. | ||||||
|     static member Empty () : VeryPublicTypeMock<'a, 'b> = |     static member Empty () : VeryPublicTypeMock<'a, 'b> = | ||||||
|         { |         { | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     interface VeryPublicType<'a, 'b> with |     interface VeryPublicType<'a, 'b> with | ||||||
|         member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0) |         member this.Mem1 (arg_0_0) = this.Mem1 (arg_0_0) | ||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| /// Mock record type for an interface | /// Mock record type for an interface | ||||||
| @@ -157,18 +150,18 @@ type internal CurriedMock<'a> = | |||||||
|     /// An implementation where every method throws. |     /// An implementation where every method throws. | ||||||
|     static member Empty () : CurriedMock<'a> = |     static member Empty () : CurriedMock<'a> = | ||||||
|         { |         { | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem3 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem3 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem4 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem4 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem5 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem5 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|             Mem6 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |             Mem6 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function")) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     interface Curried<'a> with |     interface Curried<'a> with | ||||||
|         member this.Mem1 arg_0_0 arg_1_0 = this.Mem1 (arg_0_0) (arg_1_0) |         member this.Mem1 (arg_0_0) (arg_1_0) = this.Mem1 (arg_0_0) (arg_1_0) | ||||||
|         member this.Mem2 (arg_0_0, arg_0_1) arg_1_0 = this.Mem2 (arg_0_0, arg_0_1) (arg_1_0) |         member this.Mem2 (arg_0_0, arg_0_1) (arg_1_0) = this.Mem2 (arg_0_0, arg_0_1) (arg_1_0) | ||||||
|         member this.Mem3 ((arg_0_0, arg_0_1)) arg_1_0 = this.Mem3 (arg_0_0, arg_0_1) (arg_1_0) |         member this.Mem3 ((arg_0_0, arg_0_1)) (arg_1_0) = this.Mem3 (arg_0_0, arg_0_1) (arg_1_0) | ||||||
|  |  | ||||||
|         member this.Mem4 ((arg_0_0, arg_0_1)) ((arg_1_0, arg_1_1)) = |         member this.Mem4 ((arg_0_0, arg_0_1)) ((arg_1_0, arg_1_1)) = | ||||||
|             this.Mem4 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) |             this.Mem4 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) | ||||||
| @@ -178,31 +171,3 @@ type internal CurriedMock<'a> = | |||||||
|  |  | ||||||
|         member this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) = |         member this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) = | ||||||
|             this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) |             this.Mem6 (arg_0_0, arg_0_1) (arg_1_0, arg_1_1) | ||||||
| namespace SomeNamespace |  | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| /// Mock record type for an interface |  | ||||||
| type internal TypeWithInterfaceMock = |  | ||||||
|     { |  | ||||||
|         /// Implementation of IDisposable.Dispose |  | ||||||
|         Dispose : unit -> unit |  | ||||||
|         Mem1 : string option -> string[] Async |  | ||||||
|         Mem2 : unit -> string[] Async |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// An implementation where every method throws. |  | ||||||
|     static member Empty : TypeWithInterfaceMock = |  | ||||||
|         { |  | ||||||
|             Dispose = (fun () -> ()) |  | ||||||
|             Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |  | ||||||
|             Mem2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function")) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     interface TypeWithInterface with |  | ||||||
|         member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0) |  | ||||||
|         member this.Mem2 () = this.Mem2 (()) |  | ||||||
|  |  | ||||||
|     interface System.IDisposable with |  | ||||||
|         member this.Dispose () : unit = this.Dispose () |  | ||||||
|   | |||||||
| @@ -41,11 +41,12 @@ module MemberJsonSerializeExtension = | |||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the GymOpeningHours type | /// Module containing JSON parsing methods for the GymOpeningHours type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module GymOpeningHours = | module GymOpeningHours = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymOpeningHours = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymOpeningHours = | ||||||
|         let arg_1 = |         let OpeningHours = | ||||||
|             (match node.["openingHours"] with |             (match node.["openingHours"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -58,7 +59,7 @@ module GymOpeningHours = | |||||||
|             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) |             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) | ||||||
|             |> List.ofSeq |             |> List.ofSeq | ||||||
|  |  | ||||||
|         let arg_0 = |         let IsAlwaysOpen = | ||||||
|             (match node.["isAlwaysOpen"] with |             (match node.["isAlwaysOpen"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -71,17 +72,18 @@ module GymOpeningHours = | |||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             IsAlwaysOpen = arg_0 |             IsAlwaysOpen = IsAlwaysOpen | ||||||
|             OpeningHours = arg_1 |             OpeningHours = OpeningHours | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the GymAccessOptions type | /// Module containing JSON parsing methods for the GymAccessOptions type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module GymAccessOptions = | module GymAccessOptions = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAccessOptions = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAccessOptions = | ||||||
|         let arg_1 = |         let QrCodeAccess = | ||||||
|             (match node.["qrCodeAccess"] with |             (match node.["qrCodeAccess"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -93,7 +95,7 @@ module GymAccessOptions = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let PinAccess = | ||||||
|             (match node.["pinAccess"] with |             (match node.["pinAccess"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -106,17 +108,18 @@ module GymAccessOptions = | |||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             PinAccess = arg_0 |             PinAccess = PinAccess | ||||||
|             QrCodeAccess = arg_1 |             QrCodeAccess = QrCodeAccess | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the GymLocation type | /// Module containing JSON parsing methods for the GymLocation type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module GymLocation = | module GymLocation = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymLocation = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymLocation = | ||||||
|         let arg_1 = |         let Latitude = | ||||||
|             try |             try | ||||||
|                 (match node.["latitude"] with |                 (match node.["latitude"] with | ||||||
|                  | null -> |                  | null -> | ||||||
| @@ -149,7 +152,7 @@ module GymLocation = | |||||||
|                 else |                 else | ||||||
|                     reraise () |                     reraise () | ||||||
|  |  | ||||||
|         let arg_0 = |         let Longitude = | ||||||
|             try |             try | ||||||
|                 (match node.["longitude"] with |                 (match node.["longitude"] with | ||||||
|                  | null -> |                  | null -> | ||||||
| @@ -183,17 +186,18 @@ module GymLocation = | |||||||
|                     reraise () |                     reraise () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Longitude = arg_0 |             Longitude = Longitude | ||||||
|             Latitude = arg_1 |             Latitude = Latitude | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the GymAddress type | /// Module containing JSON parsing methods for the GymAddress type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module GymAddress = | module GymAddress = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAddress = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAddress = | ||||||
|         let arg_5 = |         let Postcode = | ||||||
|             (match node.["postcode"] with |             (match node.["postcode"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -205,12 +209,12 @@ module GymAddress = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_4 = |         let County = | ||||||
|             match node.["county"] with |             match node.["county"] with | ||||||
|             | null -> None |             | null -> None | ||||||
|             | v -> v.AsValue().GetValue<string> () |> Some |             | v -> v.AsValue().GetValue<string> () |> Some | ||||||
|  |  | ||||||
|         let arg_3 = |         let Town = | ||||||
|             (match node.["town"] with |             (match node.["town"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -222,17 +226,17 @@ module GymAddress = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_2 = |         let AddressLine3 = | ||||||
|             match node.["addressLine3"] with |             match node.["addressLine3"] with | ||||||
|             | null -> None |             | null -> None | ||||||
|             | v -> v.AsValue().GetValue<string> () |> Some |             | v -> v.AsValue().GetValue<string> () |> Some | ||||||
|  |  | ||||||
|         let arg_1 = |         let AddressLine2 = | ||||||
|             match node.["addressLine2"] with |             match node.["addressLine2"] with | ||||||
|             | null -> None |             | null -> None | ||||||
|             | v -> v.AsValue().GetValue<string> () |> Some |             | v -> v.AsValue().GetValue<string> () |> Some | ||||||
|  |  | ||||||
|         let arg_0 = |         let AddressLine1 = | ||||||
|             (match node.["addressLine1"] with |             (match node.["addressLine1"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -245,21 +249,22 @@ module GymAddress = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             AddressLine1 = arg_0 |             AddressLine1 = AddressLine1 | ||||||
|             AddressLine2 = arg_1 |             AddressLine2 = AddressLine2 | ||||||
|             AddressLine3 = arg_2 |             AddressLine3 = AddressLine3 | ||||||
|             Town = arg_3 |             Town = Town | ||||||
|             County = arg_4 |             County = County | ||||||
|             Postcode = arg_5 |             Postcode = Postcode | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the Gym type | /// Module containing JSON parsing methods for the Gym type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module Gym = | module Gym = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Gym = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Gym = | ||||||
|         let arg_10 = |         let ReopenDate = | ||||||
|             (match node.["reopenDate"] with |             (match node.["reopenDate"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -271,7 +276,7 @@ module Gym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_9 = |         let TimeZone = | ||||||
|             (match node.["timeZone"] with |             (match node.["timeZone"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -283,7 +288,7 @@ module Gym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_8 = |         let Location = | ||||||
|             GymLocation.jsonParse ( |             GymLocation.jsonParse ( | ||||||
|                 match node.["location"] with |                 match node.["location"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -295,7 +300,7 @@ module Gym = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_7 = |         let AccessOptions = | ||||||
|             GymAccessOptions.jsonParse ( |             GymAccessOptions.jsonParse ( | ||||||
|                 match node.["accessOptions"] with |                 match node.["accessOptions"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -307,7 +312,7 @@ module Gym = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_6 = |         let GymOpeningHours = | ||||||
|             GymOpeningHours.jsonParse ( |             GymOpeningHours.jsonParse ( | ||||||
|                 match node.["gymOpeningHours"] with |                 match node.["gymOpeningHours"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -319,7 +324,7 @@ module Gym = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_5 = |         let EmailAddress = | ||||||
|             (match node.["emailAddress"] with |             (match node.["emailAddress"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -331,7 +336,7 @@ module Gym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_4 = |         let PhoneNumber = | ||||||
|             (match node.["phoneNumber"] with |             (match node.["phoneNumber"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -343,7 +348,7 @@ module Gym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_3 = |         let Address = | ||||||
|             GymAddress.jsonParse ( |             GymAddress.jsonParse ( | ||||||
|                 match node.["address"] with |                 match node.["address"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -355,7 +360,7 @@ module Gym = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_2 = |         let Status = | ||||||
|             (match node.["status"] with |             (match node.["status"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -367,7 +372,7 @@ module Gym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let Id = | ||||||
|             (match node.["id"] with |             (match node.["id"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -379,7 +384,7 @@ module Gym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let Name = | ||||||
|             (match node.["name"] with |             (match node.["name"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -392,17 +397,17 @@ module Gym = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Name = arg_0 |             Name = Name | ||||||
|             Id = arg_1 |             Id = Id | ||||||
|             Status = arg_2 |             Status = Status | ||||||
|             Address = arg_3 |             Address = Address | ||||||
|             PhoneNumber = arg_4 |             PhoneNumber = PhoneNumber | ||||||
|             EmailAddress = arg_5 |             EmailAddress = EmailAddress | ||||||
|             GymOpeningHours = arg_6 |             GymOpeningHours = GymOpeningHours | ||||||
|             AccessOptions = arg_7 |             AccessOptions = AccessOptions | ||||||
|             Location = arg_8 |             Location = Location | ||||||
|             TimeZone = arg_9 |             TimeZone = TimeZone | ||||||
|             ReopenDate = arg_10 |             ReopenDate = ReopenDate | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| @@ -414,7 +419,7 @@ module MemberJsonParseExtension = | |||||||
|  |  | ||||||
|         /// Parse from a JSON node. |         /// Parse from a JSON node. | ||||||
|         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : Member = |         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : Member = | ||||||
|             let arg_14 = |             let MemberStatus = | ||||||
|                 (match node.["memberStatus"] with |                 (match node.["memberStatus"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -426,7 +431,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<int> () |                     .GetValue<int> () | ||||||
|  |  | ||||||
|             let arg_13 = |             let SuspendedReason = | ||||||
|                 (match node.["suspendedReason"] with |                 (match node.["suspendedReason"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -438,7 +443,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<int> () |                     .GetValue<int> () | ||||||
|  |  | ||||||
|             let arg_12 = |             let MembershipLevel = | ||||||
|                 (match node.["membershipLevel"] with |                 (match node.["membershipLevel"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -450,7 +455,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<int> () |                     .GetValue<int> () | ||||||
|  |  | ||||||
|             let arg_11 = |             let MembershipName = | ||||||
|                 (match node.["membershipName"] with |                 (match node.["membershipName"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -462,7 +467,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_10 = |             let Postcode = | ||||||
|                 (match node.["postCode"] with |                 (match node.["postCode"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -474,7 +479,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_9 = |             let MobileNumber = | ||||||
|                 (match node.["mobileNumber"] with |                 (match node.["mobileNumber"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -486,7 +491,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_8 = |             let DateOfBirth = | ||||||
|                 (match node.["dateofBirth"] with |                 (match node.["dateofBirth"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -499,7 +504,7 @@ module MemberJsonParseExtension = | |||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|                 |> System.DateOnly.Parse |                 |> System.DateOnly.Parse | ||||||
|  |  | ||||||
|             let arg_7 = |             let GymAccessPin = | ||||||
|                 (match node.["gymAccessPin"] with |                 (match node.["gymAccessPin"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -511,7 +516,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_6 = |             let EmailAddress = | ||||||
|                 (match node.["emailAddress"] with |                 (match node.["emailAddress"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -523,7 +528,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_5 = |             let HomeGymName = | ||||||
|                 (match node.["homeGymName"] with |                 (match node.["homeGymName"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -535,7 +540,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_4 = |             let HomeGymId = | ||||||
|                 (match node.["homeGymId"] with |                 (match node.["homeGymId"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -547,7 +552,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<int> () |                     .GetValue<int> () | ||||||
|  |  | ||||||
|             let arg_3 = |             let LastName = | ||||||
|                 (match node.["lastName"] with |                 (match node.["lastName"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -559,7 +564,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_2 = |             let FirstName = | ||||||
|                 (match node.["firstName"] with |                 (match node.["firstName"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -571,7 +576,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_1 = |             let CompoundMemberId = | ||||||
|                 (match node.["compoundMemberId"] with |                 (match node.["compoundMemberId"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -583,7 +588,7 @@ module MemberJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_0 = |             let Id = | ||||||
|                 (match node.["id"] with |                 (match node.["id"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -596,30 +601,31 @@ module MemberJsonParseExtension = | |||||||
|                     .GetValue<int> () |                     .GetValue<int> () | ||||||
|  |  | ||||||
|             { |             { | ||||||
|                 Id = arg_0 |                 Id = Id | ||||||
|                 CompoundMemberId = arg_1 |                 CompoundMemberId = CompoundMemberId | ||||||
|                 FirstName = arg_2 |                 FirstName = FirstName | ||||||
|                 LastName = arg_3 |                 LastName = LastName | ||||||
|                 HomeGymId = arg_4 |                 HomeGymId = HomeGymId | ||||||
|                 HomeGymName = arg_5 |                 HomeGymName = HomeGymName | ||||||
|                 EmailAddress = arg_6 |                 EmailAddress = EmailAddress | ||||||
|                 GymAccessPin = arg_7 |                 GymAccessPin = GymAccessPin | ||||||
|                 DateOfBirth = arg_8 |                 DateOfBirth = DateOfBirth | ||||||
|                 MobileNumber = arg_9 |                 MobileNumber = MobileNumber | ||||||
|                 Postcode = arg_10 |                 Postcode = Postcode | ||||||
|                 MembershipName = arg_11 |                 MembershipName = MembershipName | ||||||
|                 MembershipLevel = arg_12 |                 MembershipLevel = MembershipLevel | ||||||
|                 SuspendedReason = arg_13 |                 SuspendedReason = SuspendedReason | ||||||
|                 MemberStatus = arg_14 |                 MemberStatus = MemberStatus | ||||||
|             } |             } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the GymAttendance type | /// Module containing JSON parsing methods for the GymAttendance type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module GymAttendance = | module GymAttendance = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAttendance = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : GymAttendance = | ||||||
|         let arg_8 = |         let MaximumCapacity = | ||||||
|             (match node.["maximumCapacity"] with |             (match node.["maximumCapacity"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -631,7 +637,7 @@ module GymAttendance = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_7 = |         let LastRefreshedPeopleInClasses = | ||||||
|             (match node.["lastRefreshedPeopleInClasses"] with |             (match node.["lastRefreshedPeopleInClasses"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -644,7 +650,7 @@ module GymAttendance = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|             |> System.DateTime.Parse |             |> System.DateTime.Parse | ||||||
|  |  | ||||||
|         let arg_6 = |         let LastRefreshed = | ||||||
|             (match node.["lastRefreshed"] with |             (match node.["lastRefreshed"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -657,7 +663,7 @@ module GymAttendance = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|             |> System.DateTime.Parse |             |> System.DateTime.Parse | ||||||
|  |  | ||||||
|         let arg_5 = |         let AttendanceTime = | ||||||
|             (match node.["attendanceTime"] with |             (match node.["attendanceTime"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -670,7 +676,7 @@ module GymAttendance = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|             |> System.DateTime.Parse |             |> System.DateTime.Parse | ||||||
|  |  | ||||||
|         let arg_4 = |         let IsApproximate = | ||||||
|             (match node.["isApproximate"] with |             (match node.["isApproximate"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -682,12 +688,12 @@ module GymAttendance = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         let arg_3 = |         let TotalPeopleSuffix = | ||||||
|             match node.["totalPeopleSuffix"] with |             match node.["totalPeopleSuffix"] with | ||||||
|             | null -> None |             | null -> None | ||||||
|             | v -> v.AsValue().GetValue<string> () |> Some |             | v -> v.AsValue().GetValue<string> () |> Some | ||||||
|  |  | ||||||
|         let arg_2 = |         let TotalPeopleInClasses = | ||||||
|             (match node.["totalPeopleInClasses"] with |             (match node.["totalPeopleInClasses"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -699,7 +705,7 @@ module GymAttendance = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let TotalPeopleInGym = | ||||||
|             (match node.["totalPeopleInGym"] with |             (match node.["totalPeopleInGym"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -711,7 +717,7 @@ module GymAttendance = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let Description = | ||||||
|             (match node.["description"] with |             (match node.["description"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -724,24 +730,25 @@ module GymAttendance = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Description = arg_0 |             Description = Description | ||||||
|             TotalPeopleInGym = arg_1 |             TotalPeopleInGym = TotalPeopleInGym | ||||||
|             TotalPeopleInClasses = arg_2 |             TotalPeopleInClasses = TotalPeopleInClasses | ||||||
|             TotalPeopleSuffix = arg_3 |             TotalPeopleSuffix = TotalPeopleSuffix | ||||||
|             IsApproximate = arg_4 |             IsApproximate = IsApproximate | ||||||
|             AttendanceTime = arg_5 |             AttendanceTime = AttendanceTime | ||||||
|             LastRefreshed = arg_6 |             LastRefreshed = LastRefreshed | ||||||
|             LastRefreshedPeopleInClasses = arg_7 |             LastRefreshedPeopleInClasses = LastRefreshedPeopleInClasses | ||||||
|             MaximumCapacity = arg_8 |             MaximumCapacity = MaximumCapacity | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the MemberActivityDto type | /// Module containing JSON parsing methods for the MemberActivityDto type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module MemberActivityDto = | module MemberActivityDto = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : MemberActivityDto = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : MemberActivityDto = | ||||||
|         let arg_5 = |         let LastRefreshed = | ||||||
|             (match node.["lastRefreshed"] with |             (match node.["lastRefreshed"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -754,7 +761,7 @@ module MemberActivityDto = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|             |> System.DateTime.Parse |             |> System.DateTime.Parse | ||||||
|  |  | ||||||
|         let arg_4 = |         let IsEstimated = | ||||||
|             (match node.["isEstimated"] with |             (match node.["isEstimated"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -766,7 +773,7 @@ module MemberActivityDto = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         let arg_3 = |         let TotalClasses = | ||||||
|             (match node.["totalClasses"] with |             (match node.["totalClasses"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -778,7 +785,7 @@ module MemberActivityDto = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_2 = |         let TotalVisits = | ||||||
|             (match node.["totalVisits"] with |             (match node.["totalVisits"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -790,7 +797,7 @@ module MemberActivityDto = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let AverageDuration = | ||||||
|             (match node.["averageDuration"] with |             (match node.["averageDuration"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -802,7 +809,7 @@ module MemberActivityDto = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let TotalDuration = | ||||||
|             (match node.["totalDuration"] with |             (match node.["totalDuration"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -815,21 +822,22 @@ module MemberActivityDto = | |||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             TotalDuration = arg_0 |             TotalDuration = TotalDuration | ||||||
|             AverageDuration = arg_1 |             AverageDuration = AverageDuration | ||||||
|             TotalVisits = arg_2 |             TotalVisits = TotalVisits | ||||||
|             TotalClasses = arg_3 |             TotalClasses = TotalClasses | ||||||
|             IsEstimated = arg_4 |             IsEstimated = IsEstimated | ||||||
|             LastRefreshed = arg_5 |             LastRefreshed = LastRefreshed | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the SessionsAggregate type | /// Module containing JSON parsing methods for the SessionsAggregate type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module SessionsAggregate = | module SessionsAggregate = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate = | ||||||
|         let arg_2 = |         let Duration = | ||||||
|             (match node.["Duration"] with |             (match node.["Duration"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -841,7 +849,7 @@ module SessionsAggregate = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let Visits = | ||||||
|             (match node.["Visits"] with |             (match node.["Visits"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -853,7 +861,7 @@ module SessionsAggregate = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let Activities = | ||||||
|             (match node.["Activities"] with |             (match node.["Activities"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -866,18 +874,19 @@ module SessionsAggregate = | |||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Activities = arg_0 |             Activities = Activities | ||||||
|             Visits = arg_1 |             Visits = Visits | ||||||
|             Duration = arg_2 |             Duration = Duration | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the VisitGym type | /// Module containing JSON parsing methods for the VisitGym type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module VisitGym = | module VisitGym = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym = | ||||||
|         let arg_2 = |         let Status = | ||||||
|             (match node.["Status"] with |             (match node.["Status"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -889,7 +898,7 @@ module VisitGym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let Name = | ||||||
|             (match node.["Name"] with |             (match node.["Name"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -901,7 +910,7 @@ module VisitGym = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let Id = | ||||||
|             (match node.["Id"] with |             (match node.["Id"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -914,18 +923,19 @@ module VisitGym = | |||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Id = arg_0 |             Id = Id | ||||||
|             Name = arg_1 |             Name = Name | ||||||
|             Status = arg_2 |             Status = Status | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the Visit type | /// Module containing JSON parsing methods for the Visit type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module Visit = | module Visit = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit = | ||||||
|         let arg_3 = |         let Gym = | ||||||
|             VisitGym.jsonParse ( |             VisitGym.jsonParse ( | ||||||
|                 match node.["Gym"] with |                 match node.["Gym"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -937,7 +947,7 @@ module Visit = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_2 = |         let Duration = | ||||||
|             (match node.["Duration"] with |             (match node.["Duration"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -949,7 +959,7 @@ module Visit = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let StartTime = | ||||||
|             (match node.["StartTime"] with |             (match node.["StartTime"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -962,7 +972,7 @@ module Visit = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|             |> System.DateTime.Parse |             |> System.DateTime.Parse | ||||||
|  |  | ||||||
|         let arg_0 = |         let IsDurationEstimated = | ||||||
|             (match node.["IsDurationEstimated"] with |             (match node.["IsDurationEstimated"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -975,19 +985,20 @@ module Visit = | |||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             IsDurationEstimated = arg_0 |             IsDurationEstimated = IsDurationEstimated | ||||||
|             StartTime = arg_1 |             StartTime = StartTime | ||||||
|             Duration = arg_2 |             Duration = Duration | ||||||
|             Gym = arg_3 |             Gym = Gym | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the SessionsSummary type | /// Module containing JSON parsing methods for the SessionsSummary type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module SessionsSummary = | module SessionsSummary = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary = | ||||||
|         let arg_1 = |         let ThisWeek = | ||||||
|             SessionsAggregate.jsonParse ( |             SessionsAggregate.jsonParse ( | ||||||
|                 match node.["ThisWeek"] with |                 match node.["ThisWeek"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -999,7 +1010,7 @@ module SessionsSummary = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_0 = |         let Total = | ||||||
|             SessionsAggregate.jsonParse ( |             SessionsAggregate.jsonParse ( | ||||||
|                 match node.["Total"] with |                 match node.["Total"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -1012,17 +1023,18 @@ module SessionsSummary = | |||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Total = arg_0 |             Total = Total | ||||||
|             ThisWeek = arg_1 |             ThisWeek = ThisWeek | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the Sessions type | /// Module containing JSON parsing methods for the Sessions type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module Sessions = | module Sessions = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions = | ||||||
|         let arg_1 = |         let Visits = | ||||||
|             (match node.["Visits"] with |             (match node.["Visits"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -1035,7 +1047,7 @@ module Sessions = | |||||||
|             |> Seq.map (fun elt -> Visit.jsonParse elt) |             |> Seq.map (fun elt -> Visit.jsonParse elt) | ||||||
|             |> List.ofSeq |             |> List.ofSeq | ||||||
|  |  | ||||||
|         let arg_0 = |         let Summary = | ||||||
|             SessionsSummary.jsonParse ( |             SessionsSummary.jsonParse ( | ||||||
|                 match node.["Summary"] with |                 match node.["Summary"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -1048,17 +1060,18 @@ module Sessions = | |||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Summary = arg_0 |             Summary = Summary | ||||||
|             Visits = arg_1 |             Visits = Visits | ||||||
|         } |         } | ||||||
| namespace PureGym | namespace PureGym | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the UriThing type | /// Module containing JSON parsing methods for the UriThing type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module UriThing = | module UriThing = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing = | ||||||
|         let arg_0 = |         let SomeUri = | ||||||
|             (match node.["someUri"] with |             (match node.["someUri"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -1072,5 +1085,5 @@ module UriThing = | |||||||
|             |> System.Uri |             |> System.Uri | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             SomeUri = arg_0 |             SomeUri = SomeUri | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -17,7 +17,8 @@ open System.Net.Http | |||||||
| open RestEase | open RestEase | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. | /// Module for constructing a REST client. | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
| module PureGymApi = | module PureGymApi = | ||||||
|     /// Create a REST client. |     /// Create a REST client. | ||||||
|     let make (client : System.Net.Http.HttpClient) : IPureGymApi = |     let make (client : System.Net.Http.HttpClient) : IPureGymApi = | ||||||
| @@ -86,40 +87,6 @@ module PureGymApi = | |||||||
|                 } |                 } | ||||||
|                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) | ||||||
|  |  | ||||||
|             member _.GetGymAttendance' (gymId : int, ct : CancellationToken option) = |  | ||||||
|                 async { |  | ||||||
|                     let! ct = Async.CancellationToken |  | ||||||
|  |  | ||||||
|                     let uri = |  | ||||||
|                         System.Uri ( |  | ||||||
|                             (match client.BaseAddress with |  | ||||||
|                              | null -> System.Uri "https://whatnot.com" |  | ||||||
|                              | v -> v), |  | ||||||
|                             System.Uri ( |  | ||||||
|                                 "v1/gyms/{gym_id}/attendance" |  | ||||||
|                                     .Replace ("{gym_id}", gymId.ToString () |> System.Web.HttpUtility.UrlEncode), |  | ||||||
|                                 System.UriKind.Relative |  | ||||||
|                             ) |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let httpMessage = |  | ||||||
|                         new System.Net.Http.HttpRequestMessage ( |  | ||||||
|                             Method = System.Net.Http.HttpMethod.Get, |  | ||||||
|                             RequestUri = uri |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask |  | ||||||
|                     let response = response.EnsureSuccessStatusCode () |  | ||||||
|                     let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     let! jsonNode = |  | ||||||
|                         System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct) |  | ||||||
|                         |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     return GymAttendance.jsonParse jsonNode |  | ||||||
|                 } |  | ||||||
|                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |  | ||||||
|  |  | ||||||
|             member _.GetMember (ct : CancellationToken option) = |             member _.GetMember (ct : CancellationToken option) = | ||||||
|                 async { |                 async { | ||||||
|                     let! ct = Async.CancellationToken |                     let! ct = Async.CancellationToken | ||||||
| @@ -321,52 +288,7 @@ module PureGymApi = | |||||||
|                              | v -> v), |                              | v -> v), | ||||||
|                             System.Uri ( |                             System.Uri ( | ||||||
|                                 ("/v2/gymSessions/member" |                                 ("/v2/gymSessions/member" | ||||||
|                                  + (if "/v2/gymSessions/member".IndexOf (char 63) >= 0 then |                                  + "?fromDate=" | ||||||
|                                         "&" |  | ||||||
|                                     else |  | ||||||
|                                         "?") |  | ||||||
|                                  + "fromDate=" |  | ||||||
|                                  + ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode) |  | ||||||
|                                  + "&toDate=" |  | ||||||
|                                  + ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)), |  | ||||||
|                                 System.UriKind.Relative |  | ||||||
|                             ) |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let httpMessage = |  | ||||||
|                         new System.Net.Http.HttpRequestMessage ( |  | ||||||
|                             Method = System.Net.Http.HttpMethod.Get, |  | ||||||
|                             RequestUri = uri |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask |  | ||||||
|                     let response = response.EnsureSuccessStatusCode () |  | ||||||
|                     let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     let! jsonNode = |  | ||||||
|                         System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct) |  | ||||||
|                         |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     return Sessions.jsonParse jsonNode |  | ||||||
|                 } |  | ||||||
|                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |  | ||||||
|  |  | ||||||
|             member _.GetSessionsWithQuery (fromDate : DateOnly, toDate : DateOnly, ct : CancellationToken option) = |  | ||||||
|                 async { |  | ||||||
|                     let! ct = Async.CancellationToken |  | ||||||
|  |  | ||||||
|                     let uri = |  | ||||||
|                         System.Uri ( |  | ||||||
|                             (match client.BaseAddress with |  | ||||||
|                              | null -> System.Uri "https://whatnot.com" |  | ||||||
|                              | v -> v), |  | ||||||
|                             System.Uri ( |  | ||||||
|                                 ("/v2/gymSessions/member?foo=1" |  | ||||||
|                                  + (if "/v2/gymSessions/member?foo=1".IndexOf (char 63) >= 0 then |  | ||||||
|                                         "&" |  | ||||||
|                                     else |  | ||||||
|                                         "?") |  | ||||||
|                                  + "fromDate=" |  | ||||||
|                                  + ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode) |                                  + ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode) | ||||||
|                                  + "&toDate=" |                                  + "&toDate=" | ||||||
|                                  + ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)), |                                  + ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)), | ||||||
| @@ -1054,7 +976,8 @@ open System.Net.Http | |||||||
| open RestEase | open RestEase | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. | /// Module for constructing a REST client. | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
| module internal ApiWithoutBaseAddress = | module internal ApiWithoutBaseAddress = | ||||||
|     /// Create a REST client. |     /// Create a REST client. | ||||||
|     let make (client : System.Net.Http.HttpClient) : IApiWithoutBaseAddress = |     let make (client : System.Net.Http.HttpClient) : IApiWithoutBaseAddress = | ||||||
| @@ -1105,7 +1028,8 @@ open System.Net.Http | |||||||
| open RestEase | open RestEase | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. | /// Module for constructing a REST client. | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
| module ApiWithBasePath = | module ApiWithBasePath = | ||||||
|     /// Create a REST client. |     /// Create a REST client. | ||||||
|     let make (client : System.Net.Http.HttpClient) : IApiWithBasePath = |     let make (client : System.Net.Http.HttpClient) : IApiWithBasePath = | ||||||
| @@ -1156,7 +1080,8 @@ open System.Net.Http | |||||||
| open RestEase | open RestEase | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. | /// Module for constructing a REST client. | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
| module ApiWithBasePathAndAddress = | module ApiWithBasePathAndAddress = | ||||||
|     /// Create a REST client. |     /// Create a REST client. | ||||||
|     let make (client : System.Net.Http.HttpClient) : IApiWithBasePathAndAddress = |     let make (client : System.Net.Http.HttpClient) : IApiWithBasePathAndAddress = | ||||||
| @@ -1201,7 +1126,8 @@ open System.Net.Http | |||||||
| open RestEase | open RestEase | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. | /// Module for constructing a REST client. | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
| module ApiWithHeaders = | module ApiWithHeaders = | ||||||
|     /// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties. |     /// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties. | ||||||
|     let make |     let make | ||||||
| @@ -1214,68 +1140,6 @@ module ApiWithHeaders = | |||||||
|             member _.SomeHeader : string = someHeader () |             member _.SomeHeader : string = someHeader () | ||||||
|             member _.SomeOtherHeader : int = someOtherHeader () |             member _.SomeOtherHeader : int = someOtherHeader () | ||||||
|  |  | ||||||
|             member this.GetPathParam (parameter : string, ct : CancellationToken option) = |  | ||||||
|                 async { |  | ||||||
|                     let! ct = Async.CancellationToken |  | ||||||
|  |  | ||||||
|                     let uri = |  | ||||||
|                         System.Uri ( |  | ||||||
|                             (match client.BaseAddress with |  | ||||||
|                              | null -> |  | ||||||
|                                  raise ( |  | ||||||
|                                      System.ArgumentNullException ( |  | ||||||
|                                          nameof (client.BaseAddress), |  | ||||||
|                                          "No base address was supplied on the type, and no BaseAddress was on the HttpClient." |  | ||||||
|                                      ) |  | ||||||
|                                  ) |  | ||||||
|                              | v -> v), |  | ||||||
|                             System.Uri ( |  | ||||||
|                                 "endpoint/{param}" |  | ||||||
|                                     .Replace ("{param}", parameter.ToString () |> System.Web.HttpUtility.UrlEncode), |  | ||||||
|                                 System.UriKind.Relative |  | ||||||
|                             ) |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let httpMessage = |  | ||||||
|                         new System.Net.Http.HttpRequestMessage ( |  | ||||||
|                             Method = System.Net.Http.HttpMethod.Get, |  | ||||||
|                             RequestUri = uri |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     do httpMessage.Headers.Add ("X-Foo", this.SomeHeader.ToString ()) |  | ||||||
|                     do httpMessage.Headers.Add ("Authorization", this.SomeOtherHeader.ToString ()) |  | ||||||
|                     do httpMessage.Headers.Add ("Header-Name", "Header-Value") |  | ||||||
|                     let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask |  | ||||||
|                     let response = response.EnsureSuccessStatusCode () |  | ||||||
|                     let! responseString = response.Content.ReadAsStringAsync ct |> Async.AwaitTask |  | ||||||
|                     return responseString |  | ||||||
|                 } |  | ||||||
|                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |  | ||||||
|         } |  | ||||||
| namespace PureGym |  | ||||||
|  |  | ||||||
| open System |  | ||||||
| open System.Threading |  | ||||||
| open System.Threading.Tasks |  | ||||||
| open System.IO |  | ||||||
| open System.Net |  | ||||||
| open System.Net.Http |  | ||||||
| open RestEase |  | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. |  | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] |  | ||||||
| module ApiWithHeaders2 = |  | ||||||
|     /// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties. |  | ||||||
|     let make |  | ||||||
|         (someHeader : unit -> string) |  | ||||||
|         (someOtherHeader : unit -> int) |  | ||||||
|         (client : System.Net.Http.HttpClient) |  | ||||||
|         : IApiWithHeaders2 |  | ||||||
|         = |  | ||||||
|         { new IApiWithHeaders2 with |  | ||||||
|             member _.SomeHeader : string = someHeader () |  | ||||||
|             member _.SomeOtherHeader : int = someOtherHeader () |  | ||||||
|  |  | ||||||
|             member this.GetPathParam (parameter : string, ct : CancellationToken option) = |             member this.GetPathParam (parameter : string, ct : CancellationToken option) = | ||||||
|                 async { |                 async { | ||||||
|                     let! ct = Async.CancellationToken |                     let! ct = Async.CancellationToken | ||||||
|   | |||||||
| @@ -149,37 +149,6 @@ module JsonRecordTypeWithBothJsonSerializeExtension = | |||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|             node :> _ |             node :> _ | ||||||
| namespace ConsumePlugin |  | ||||||
|  |  | ||||||
| open System |  | ||||||
| open System.Collections.Generic |  | ||||||
| open System.Text.Json.Serialization |  | ||||||
|  |  | ||||||
| /// Module containing JSON serializing extension members for the FirstDu type |  | ||||||
| [<AutoOpen>] |  | ||||||
| module FirstDuJsonSerializeExtension = |  | ||||||
|     /// Extension methods for JSON parsing |  | ||||||
|     type FirstDu with |  | ||||||
|  |  | ||||||
|         /// Serialize to a JSON node |  | ||||||
|         static member toJsonNode (input : FirstDu) : System.Text.Json.Nodes.JsonNode = |  | ||||||
|             let node = System.Text.Json.Nodes.JsonObject () |  | ||||||
|  |  | ||||||
|             match input with |  | ||||||
|             | FirstDu.EmptyCase -> node.Add ("type", System.Text.Json.Nodes.JsonValue.Create "emptyCase") |  | ||||||
|             | FirstDu.Case1 arg0 -> |  | ||||||
|                 node.Add ("type", System.Text.Json.Nodes.JsonValue.Create "case1") |  | ||||||
|                 let dataNode = System.Text.Json.Nodes.JsonObject () |  | ||||||
|                 dataNode.Add ("data", System.Text.Json.Nodes.JsonValue.Create<string> arg0) |  | ||||||
|                 node.Add ("data", dataNode) |  | ||||||
|             | FirstDu.Case2 (arg0, arg1) -> |  | ||||||
|                 node.Add ("type", System.Text.Json.Nodes.JsonValue.Create "case2") |  | ||||||
|                 let dataNode = System.Text.Json.Nodes.JsonObject () |  | ||||||
|                 dataNode.Add ("record", JsonRecordTypeWithBoth.toJsonNode arg0) |  | ||||||
|                 dataNode.Add ("i", System.Text.Json.Nodes.JsonValue.Create<int> arg1) |  | ||||||
|                 node.Add ("data", dataNode) |  | ||||||
|  |  | ||||||
|             node :> _ |  | ||||||
|  |  | ||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| @@ -191,7 +160,7 @@ module InnerTypeWithBothJsonParseExtension = | |||||||
|  |  | ||||||
|         /// Parse from a JSON node. |         /// Parse from a JSON node. | ||||||
|         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerTypeWithBoth = |         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : InnerTypeWithBoth = | ||||||
|             let arg_4 = |             let ConcreteDict = | ||||||
|                 (match node.["concreteDict"] with |                 (match node.["concreteDict"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -209,7 +178,7 @@ module InnerTypeWithBothJsonParseExtension = | |||||||
|                 |> Seq.map System.Collections.Generic.KeyValuePair |                 |> Seq.map System.Collections.Generic.KeyValuePair | ||||||
|                 |> System.Collections.Generic.Dictionary |                 |> System.Collections.Generic.Dictionary | ||||||
|  |  | ||||||
|             let arg_3 = |             let Dict = | ||||||
|                 (match node.["dict"] with |                 (match node.["dict"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -226,7 +195,7 @@ module InnerTypeWithBothJsonParseExtension = | |||||||
|                 ) |                 ) | ||||||
|                 |> dict |                 |> dict | ||||||
|  |  | ||||||
|             let arg_2 = |             let ReadOnlyDict = | ||||||
|                 (match node.["readOnlyDict"] with |                 (match node.["readOnlyDict"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -241,14 +210,14 @@ module InnerTypeWithBothJsonParseExtension = | |||||||
|  |  | ||||||
|                     let value = |                     let value = | ||||||
|                         (kvp.Value).AsArray () |                         (kvp.Value).AsArray () | ||||||
|                         |> Seq.map (fun elt -> elt.AsValue().GetValue<System.Char> ()) |                         |> Seq.map (fun elt -> elt.AsValue().GetValue<char> ()) | ||||||
|                         |> List.ofSeq |                         |> List.ofSeq | ||||||
|  |  | ||||||
|                     key, value |                     key, value | ||||||
|                 ) |                 ) | ||||||
|                 |> readOnlyDict |                 |> readOnlyDict | ||||||
|  |  | ||||||
|             let arg_1 = |             let Map = | ||||||
|                 (match node.["map"] with |                 (match node.["map"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -265,7 +234,7 @@ module InnerTypeWithBothJsonParseExtension = | |||||||
|                 ) |                 ) | ||||||
|                 |> Map.ofSeq |                 |> Map.ofSeq | ||||||
|  |  | ||||||
|             let arg_0 = |             let Thing = | ||||||
|                 (match node.[("it's-a-me")] with |                 (match node.[("it's-a-me")] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -279,11 +248,11 @@ module InnerTypeWithBothJsonParseExtension = | |||||||
|                 |> System.Guid.Parse |                 |> System.Guid.Parse | ||||||
|  |  | ||||||
|             { |             { | ||||||
|                 Thing = arg_0 |                 Thing = Thing | ||||||
|                 Map = arg_1 |                 Map = Map | ||||||
|                 ReadOnlyDict = arg_2 |                 ReadOnlyDict = ReadOnlyDict | ||||||
|                 Dict = arg_3 |                 Dict = Dict | ||||||
|                 ConcreteDict = arg_4 |                 ConcreteDict = ConcreteDict | ||||||
|             } |             } | ||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| @@ -295,7 +264,7 @@ module JsonRecordTypeWithBothJsonParseExtension = | |||||||
|  |  | ||||||
|         /// Parse from a JSON node. |         /// Parse from a JSON node. | ||||||
|         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordTypeWithBoth = |         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : JsonRecordTypeWithBoth = | ||||||
|             let arg_5 = |             let F = | ||||||
|                 (match node.["f"] with |                 (match node.["f"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -308,7 +277,7 @@ module JsonRecordTypeWithBothJsonParseExtension = | |||||||
|                 |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) |                 |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) | ||||||
|                 |> Array.ofSeq |                 |> Array.ofSeq | ||||||
|  |  | ||||||
|             let arg_4 = |             let E = | ||||||
|                 (match node.["e"] with |                 (match node.["e"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -321,7 +290,7 @@ module JsonRecordTypeWithBothJsonParseExtension = | |||||||
|                 |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) |                 |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) | ||||||
|                 |> Array.ofSeq |                 |> Array.ofSeq | ||||||
|  |  | ||||||
|             let arg_3 = |             let D = | ||||||
|                 InnerTypeWithBoth.jsonParse ( |                 InnerTypeWithBoth.jsonParse ( | ||||||
|                     match node.["d"] with |                     match node.["d"] with | ||||||
|                     | null -> |                     | null -> | ||||||
| @@ -333,7 +302,7 @@ module JsonRecordTypeWithBothJsonParseExtension = | |||||||
|                     | v -> v |                     | v -> v | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|             let arg_2 = |             let C = | ||||||
|                 (match node.["c"] with |                 (match node.["c"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -346,7 +315,7 @@ module JsonRecordTypeWithBothJsonParseExtension = | |||||||
|                 |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) |                 |> Seq.map (fun elt -> elt.AsValue().GetValue<int> ()) | ||||||
|                 |> List.ofSeq |                 |> List.ofSeq | ||||||
|  |  | ||||||
|             let arg_1 = |             let B = | ||||||
|                 (match node.["b"] with |                 (match node.["b"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -358,7 +327,7 @@ module JsonRecordTypeWithBothJsonParseExtension = | |||||||
|                     .AsValue() |                     .AsValue() | ||||||
|                     .GetValue<string> () |                     .GetValue<string> () | ||||||
|  |  | ||||||
|             let arg_0 = |             let A = | ||||||
|                 (match node.["a"] with |                 (match node.["a"] with | ||||||
|                  | null -> |                  | null -> | ||||||
|                      raise ( |                      raise ( | ||||||
| @@ -371,90 +340,10 @@ module JsonRecordTypeWithBothJsonParseExtension = | |||||||
|                     .GetValue<int> () |                     .GetValue<int> () | ||||||
|  |  | ||||||
|             { |             { | ||||||
|                 A = arg_0 |                 A = A | ||||||
|                 B = arg_1 |                 B = B | ||||||
|                 C = arg_2 |                 C = C | ||||||
|                 D = arg_3 |                 D = D | ||||||
|                 E = arg_4 |                 E = E | ||||||
|                 F = arg_5 |                 F = F | ||||||
|             } |             } | ||||||
| namespace ConsumePlugin |  | ||||||
|  |  | ||||||
| /// Module containing JSON parsing extension members for the FirstDu type |  | ||||||
| [<AutoOpen>] |  | ||||||
| module FirstDuJsonParseExtension = |  | ||||||
|     /// Extension methods for JSON parsing |  | ||||||
|     type FirstDu with |  | ||||||
|  |  | ||||||
|         /// Parse from a JSON node. |  | ||||||
|         static member jsonParse (node : System.Text.Json.Nodes.JsonNode) : FirstDu = |  | ||||||
|             let ty = |  | ||||||
|                 (match node.["type"] with |  | ||||||
|                  | null -> |  | ||||||
|                      raise ( |  | ||||||
|                          System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                              sprintf "Required key '%s' not found on JSON object" ("type") |  | ||||||
|                          ) |  | ||||||
|                      ) |  | ||||||
|                  | v -> v) |  | ||||||
|                 |> (fun v -> v.GetValue<string> ()) |  | ||||||
|  |  | ||||||
|             match ty with |  | ||||||
|             | "emptyCase" -> FirstDu.EmptyCase |  | ||||||
|             | "case1" -> |  | ||||||
|                 let node = |  | ||||||
|                     (match node.["data"] with |  | ||||||
|                      | null -> |  | ||||||
|                          raise ( |  | ||||||
|                              System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                                  sprintf "Required key '%s' not found on JSON object" ("data") |  | ||||||
|                              ) |  | ||||||
|                          ) |  | ||||||
|                      | v -> v) |  | ||||||
|  |  | ||||||
|                 FirstDu.Case1 ( |  | ||||||
|                     (match node.["data"] with |  | ||||||
|                      | null -> |  | ||||||
|                          raise ( |  | ||||||
|                              System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                                  sprintf "Required key '%s' not found on JSON object" ("data") |  | ||||||
|                              ) |  | ||||||
|                          ) |  | ||||||
|                      | v -> v) |  | ||||||
|                         .AsValue() |  | ||||||
|                         .GetValue<string> () |  | ||||||
|                 ) |  | ||||||
|             | "case2" -> |  | ||||||
|                 let node = |  | ||||||
|                     (match node.["data"] with |  | ||||||
|                      | null -> |  | ||||||
|                          raise ( |  | ||||||
|                              System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                                  sprintf "Required key '%s' not found on JSON object" ("data") |  | ||||||
|                              ) |  | ||||||
|                          ) |  | ||||||
|                      | v -> v) |  | ||||||
|  |  | ||||||
|                 FirstDu.Case2 ( |  | ||||||
|                     JsonRecordTypeWithBoth.jsonParse ( |  | ||||||
|                         match node.["record"] with |  | ||||||
|                         | null -> |  | ||||||
|                             raise ( |  | ||||||
|                                 System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                                     sprintf "Required key '%s' not found on JSON object" ("record") |  | ||||||
|                                 ) |  | ||||||
|                             ) |  | ||||||
|                         | v -> v |  | ||||||
|                     ), |  | ||||||
|                     (match node.["i"] with |  | ||||||
|                      | null -> |  | ||||||
|                          raise ( |  | ||||||
|                              System.Collections.Generic.KeyNotFoundException ( |  | ||||||
|                                  sprintf "Required key '%s' not found on JSON object" ("i") |  | ||||||
|                              ) |  | ||||||
|                          ) |  | ||||||
|                      | v -> v) |  | ||||||
|                         .AsValue() |  | ||||||
|                         .GetValue<int> () |  | ||||||
|                 ) |  | ||||||
|             | v -> failwith ("Unrecognised 'type' field value: " + v) |  | ||||||
|   | |||||||
| @@ -8,11 +8,12 @@ | |||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the JwtVaultAuthResponse type | /// Module containing JSON parsing methods for the JwtVaultAuthResponse type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module JwtVaultAuthResponse = | module JwtVaultAuthResponse = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultAuthResponse = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultAuthResponse = | ||||||
|         let arg_10 = |         let NumUses = | ||||||
|             (match node.["num_uses"] with |             (match node.["num_uses"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -24,7 +25,7 @@ module JwtVaultAuthResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_9 = |         let Orphan = | ||||||
|             (match node.["orphan"] with |             (match node.["orphan"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -36,7 +37,7 @@ module JwtVaultAuthResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         let arg_8 = |         let EntityId = | ||||||
|             (match node.["entity_id"] with |             (match node.["entity_id"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -48,7 +49,7 @@ module JwtVaultAuthResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_7 = |         let TokenType = | ||||||
|             (match node.["token_type"] with |             (match node.["token_type"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -60,7 +61,7 @@ module JwtVaultAuthResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_6 = |         let Renewable = | ||||||
|             (match node.["renewable"] with |             (match node.["renewable"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -72,7 +73,7 @@ module JwtVaultAuthResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         let arg_5 = |         let LeaseDuration = | ||||||
|             (match node.["lease_duration"] with |             (match node.["lease_duration"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -84,7 +85,7 @@ module JwtVaultAuthResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_4 = |         let IdentityPolicies = | ||||||
|             (match node.["identity_policies"] with |             (match node.["identity_policies"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -97,7 +98,7 @@ module JwtVaultAuthResponse = | |||||||
|             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) |             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) | ||||||
|             |> List.ofSeq |             |> List.ofSeq | ||||||
|  |  | ||||||
|         let arg_3 = |         let TokenPolicies = | ||||||
|             (match node.["token_policies"] with |             (match node.["token_policies"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -110,7 +111,7 @@ module JwtVaultAuthResponse = | |||||||
|             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) |             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) | ||||||
|             |> List.ofSeq |             |> List.ofSeq | ||||||
|  |  | ||||||
|         let arg_2 = |         let Policies = | ||||||
|             (match node.["policies"] with |             (match node.["policies"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -123,7 +124,7 @@ module JwtVaultAuthResponse = | |||||||
|             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) |             |> Seq.map (fun elt -> elt.AsValue().GetValue<string> ()) | ||||||
|             |> List.ofSeq |             |> List.ofSeq | ||||||
|  |  | ||||||
|         let arg_1 = |         let Accessor = | ||||||
|             (match node.["accessor"] with |             (match node.["accessor"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -135,7 +136,7 @@ module JwtVaultAuthResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let ClientToken = | ||||||
|             (match node.["client_token"] with |             (match node.["client_token"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -148,26 +149,27 @@ module JwtVaultAuthResponse = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             ClientToken = arg_0 |             ClientToken = ClientToken | ||||||
|             Accessor = arg_1 |             Accessor = Accessor | ||||||
|             Policies = arg_2 |             Policies = Policies | ||||||
|             TokenPolicies = arg_3 |             TokenPolicies = TokenPolicies | ||||||
|             IdentityPolicies = arg_4 |             IdentityPolicies = IdentityPolicies | ||||||
|             LeaseDuration = arg_5 |             LeaseDuration = LeaseDuration | ||||||
|             Renewable = arg_6 |             Renewable = Renewable | ||||||
|             TokenType = arg_7 |             TokenType = TokenType | ||||||
|             EntityId = arg_8 |             EntityId = EntityId | ||||||
|             Orphan = arg_9 |             Orphan = Orphan | ||||||
|             NumUses = arg_10 |             NumUses = NumUses | ||||||
|         } |         } | ||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the JwtVaultResponse type | /// Module containing JSON parsing methods for the JwtVaultResponse type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module JwtVaultResponse = | module JwtVaultResponse = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultResponse = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtVaultResponse = | ||||||
|         let arg_4 = |         let Auth = | ||||||
|             JwtVaultAuthResponse.jsonParse ( |             JwtVaultAuthResponse.jsonParse ( | ||||||
|                 match node.["auth"] with |                 match node.["auth"] with | ||||||
|                 | null -> |                 | null -> | ||||||
| @@ -179,7 +181,7 @@ module JwtVaultResponse = | |||||||
|                 | v -> v |                 | v -> v | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let arg_3 = |         let LeaseDuration = | ||||||
|             (match node.["lease_duration"] with |             (match node.["lease_duration"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -191,7 +193,7 @@ module JwtVaultResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_2 = |         let Renewable = | ||||||
|             (match node.["renewable"] with |             (match node.["renewable"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -203,7 +205,7 @@ module JwtVaultResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let LeaseId = | ||||||
|             (match node.["lease_id"] with |             (match node.["lease_id"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -215,7 +217,7 @@ module JwtVaultResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let RequestId = | ||||||
|             (match node.["request_id"] with |             (match node.["request_id"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -228,20 +230,21 @@ module JwtVaultResponse = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             RequestId = arg_0 |             RequestId = RequestId | ||||||
|             LeaseId = arg_1 |             LeaseId = LeaseId | ||||||
|             Renewable = arg_2 |             Renewable = Renewable | ||||||
|             LeaseDuration = arg_3 |             LeaseDuration = LeaseDuration | ||||||
|             Auth = arg_4 |             Auth = Auth | ||||||
|         } |         } | ||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
|  |  | ||||||
| /// Module containing JSON parsing methods for the JwtSecretResponse type | /// Module containing JSON parsing methods for the JwtSecretResponse type | ||||||
| [<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | [<RequireQualifiedAccess>] | ||||||
|  | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
| module JwtSecretResponse = | module JwtSecretResponse = | ||||||
|     /// Parse from a JSON node. |     /// Parse from a JSON node. | ||||||
|     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtSecretResponse = |     let jsonParse (node : System.Text.Json.Nodes.JsonNode) : JwtSecretResponse = | ||||||
|         let arg_11 = |         let Data8 = | ||||||
|             (match node.["data8"] with |             (match node.["data8"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -259,7 +262,7 @@ module JwtSecretResponse = | |||||||
|             |> Seq.map System.Collections.Generic.KeyValuePair |             |> Seq.map System.Collections.Generic.KeyValuePair | ||||||
|             |> System.Collections.Generic.Dictionary |             |> System.Collections.Generic.Dictionary | ||||||
|  |  | ||||||
|         let arg_10 = |         let Data7 = | ||||||
|             (match node.["data7"] with |             (match node.["data7"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -276,7 +279,7 @@ module JwtSecretResponse = | |||||||
|             ) |             ) | ||||||
|             |> Map.ofSeq |             |> Map.ofSeq | ||||||
|  |  | ||||||
|         let arg_9 = |         let Data6 = | ||||||
|             (match node.["data6"] with |             (match node.["data6"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -293,7 +296,7 @@ module JwtSecretResponse = | |||||||
|             ) |             ) | ||||||
|             |> dict |             |> dict | ||||||
|  |  | ||||||
|         let arg_8 = |         let Data5 = | ||||||
|             (match node.["data5"] with |             (match node.["data5"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -310,7 +313,7 @@ module JwtSecretResponse = | |||||||
|             ) |             ) | ||||||
|             |> readOnlyDict |             |> readOnlyDict | ||||||
|  |  | ||||||
|         let arg_7 = |         let Data4 = | ||||||
|             (match node.["data4"] with |             (match node.["data4"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -327,7 +330,7 @@ module JwtSecretResponse = | |||||||
|             ) |             ) | ||||||
|             |> Map.ofSeq |             |> Map.ofSeq | ||||||
|  |  | ||||||
|         let arg_6 = |         let Data3 = | ||||||
|             (match node.["data3"] with |             (match node.["data3"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -345,7 +348,7 @@ module JwtSecretResponse = | |||||||
|             |> Seq.map System.Collections.Generic.KeyValuePair |             |> Seq.map System.Collections.Generic.KeyValuePair | ||||||
|             |> System.Collections.Generic.Dictionary |             |> System.Collections.Generic.Dictionary | ||||||
|  |  | ||||||
|         let arg_5 = |         let Data2 = | ||||||
|             (match node.["data2"] with |             (match node.["data2"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -362,7 +365,7 @@ module JwtSecretResponse = | |||||||
|             ) |             ) | ||||||
|             |> dict |             |> dict | ||||||
|  |  | ||||||
|         let arg_4 = |         let Data = | ||||||
|             (match node.["data"] with |             (match node.["data"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -379,7 +382,7 @@ module JwtSecretResponse = | |||||||
|             ) |             ) | ||||||
|             |> readOnlyDict |             |> readOnlyDict | ||||||
|  |  | ||||||
|         let arg_3 = |         let LeaseDuration = | ||||||
|             (match node.["lease_duration"] with |             (match node.["lease_duration"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -391,7 +394,7 @@ module JwtSecretResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<int> () |                 .GetValue<int> () | ||||||
|  |  | ||||||
|         let arg_2 = |         let Renewable = | ||||||
|             (match node.["renewable"] with |             (match node.["renewable"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -403,7 +406,7 @@ module JwtSecretResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<bool> () |                 .GetValue<bool> () | ||||||
|  |  | ||||||
|         let arg_1 = |         let LeaseId = | ||||||
|             (match node.["lease_id"] with |             (match node.["lease_id"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -415,7 +418,7 @@ module JwtSecretResponse = | |||||||
|                 .AsValue() |                 .AsValue() | ||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         let arg_0 = |         let RequestId = | ||||||
|             (match node.["request_id"] with |             (match node.["request_id"] with | ||||||
|              | null -> |              | null -> | ||||||
|                  raise ( |                  raise ( | ||||||
| @@ -428,18 +431,18 @@ module JwtSecretResponse = | |||||||
|                 .GetValue<string> () |                 .GetValue<string> () | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             RequestId = arg_0 |             RequestId = RequestId | ||||||
|             LeaseId = arg_1 |             LeaseId = LeaseId | ||||||
|             Renewable = arg_2 |             Renewable = Renewable | ||||||
|             LeaseDuration = arg_3 |             LeaseDuration = LeaseDuration | ||||||
|             Data = arg_4 |             Data = Data | ||||||
|             Data2 = arg_5 |             Data2 = Data2 | ||||||
|             Data3 = arg_6 |             Data3 = Data3 | ||||||
|             Data4 = arg_7 |             Data4 = Data4 | ||||||
|             Data5 = arg_8 |             Data5 = Data5 | ||||||
|             Data6 = arg_9 |             Data6 = Data6 | ||||||
|             Data7 = arg_10 |             Data7 = Data7 | ||||||
|             Data8 = arg_11 |             Data8 = Data8 | ||||||
|         } |         } | ||||||
|  |  | ||||||
| namespace ConsumePlugin | namespace ConsumePlugin | ||||||
| @@ -452,7 +455,8 @@ open System.Threading.Tasks | |||||||
| open RestEase | open RestEase | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. | /// Module for constructing a REST client. | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] | [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
| module VaultClient = | module VaultClient = | ||||||
|     /// Create a REST client. |     /// Create a REST client. | ||||||
|     let make (client : System.Net.Http.HttpClient) : IVaultClient = |     let make (client : System.Net.Http.HttpClient) : IVaultClient = | ||||||
| @@ -539,200 +543,3 @@ module VaultClient = | |||||||
|                 } |                 } | ||||||
|                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) | ||||||
|         } |         } | ||||||
| namespace ConsumePlugin |  | ||||||
|  |  | ||||||
| open System |  | ||||||
| open System.Collections.Generic |  | ||||||
| open System.Text.Json.Serialization |  | ||||||
| open System.Threading |  | ||||||
| open System.Threading.Tasks |  | ||||||
| open RestEase |  | ||||||
|  |  | ||||||
| /// Module for constructing a REST client. |  | ||||||
| [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>] |  | ||||||
| module VaultClientNonExtensionMethod = |  | ||||||
|     /// Create a REST client. |  | ||||||
|     let make (client : System.Net.Http.HttpClient) : IVaultClientNonExtensionMethod = |  | ||||||
|         { new IVaultClientNonExtensionMethod with |  | ||||||
|             member _.GetSecret |  | ||||||
|                 (jwt : JwtVaultResponse, path : string, mountPoint : string, ct : CancellationToken option) |  | ||||||
|                 = |  | ||||||
|                 async { |  | ||||||
|                     let! ct = Async.CancellationToken |  | ||||||
|  |  | ||||||
|                     let uri = |  | ||||||
|                         System.Uri ( |  | ||||||
|                             (match client.BaseAddress with |  | ||||||
|                              | null -> |  | ||||||
|                                  raise ( |  | ||||||
|                                      System.ArgumentNullException ( |  | ||||||
|                                          nameof (client.BaseAddress), |  | ||||||
|                                          "No base address was supplied on the type, and no BaseAddress was on the HttpClient." |  | ||||||
|                                      ) |  | ||||||
|                                  ) |  | ||||||
|                              | v -> v), |  | ||||||
|                             System.Uri ( |  | ||||||
|                                 "v1/{mountPoint}/{path}" |  | ||||||
|                                     .Replace("{path}", path.ToString () |> System.Web.HttpUtility.UrlEncode) |  | ||||||
|                                     .Replace ( |  | ||||||
|                                         "{mountPoint}", |  | ||||||
|                                         mountPoint.ToString () |> System.Web.HttpUtility.UrlEncode |  | ||||||
|                                     ), |  | ||||||
|                                 System.UriKind.Relative |  | ||||||
|                             ) |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let httpMessage = |  | ||||||
|                         new System.Net.Http.HttpRequestMessage ( |  | ||||||
|                             Method = System.Net.Http.HttpMethod.Get, |  | ||||||
|                             RequestUri = uri |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask |  | ||||||
|                     let response = response.EnsureSuccessStatusCode () |  | ||||||
|                     let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     let! jsonNode = |  | ||||||
|                         System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct) |  | ||||||
|                         |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     return JwtSecretResponse.jsonParse jsonNode |  | ||||||
|                 } |  | ||||||
|                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |  | ||||||
|  |  | ||||||
|             member _.GetJwt (role : string, jwt : string, ct : CancellationToken option) = |  | ||||||
|                 async { |  | ||||||
|                     let! ct = Async.CancellationToken |  | ||||||
|  |  | ||||||
|                     let uri = |  | ||||||
|                         System.Uri ( |  | ||||||
|                             (match client.BaseAddress with |  | ||||||
|                              | null -> |  | ||||||
|                                  raise ( |  | ||||||
|                                      System.ArgumentNullException ( |  | ||||||
|                                          nameof (client.BaseAddress), |  | ||||||
|                                          "No base address was supplied on the type, and no BaseAddress was on the HttpClient." |  | ||||||
|                                      ) |  | ||||||
|                                  ) |  | ||||||
|                              | v -> v), |  | ||||||
|                             System.Uri ("v1/auth/jwt/login", System.UriKind.Relative) |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let httpMessage = |  | ||||||
|                         new System.Net.Http.HttpRequestMessage ( |  | ||||||
|                             Method = System.Net.Http.HttpMethod.Get, |  | ||||||
|                             RequestUri = uri |  | ||||||
|                         ) |  | ||||||
|  |  | ||||||
|                     let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask |  | ||||||
|                     let response = response.EnsureSuccessStatusCode () |  | ||||||
|                     let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     let! jsonNode = |  | ||||||
|                         System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct) |  | ||||||
|                         |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                     return JwtVaultResponse.jsonParse jsonNode |  | ||||||
|                 } |  | ||||||
|                 |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |  | ||||||
|         } |  | ||||||
| namespace ConsumePlugin |  | ||||||
|  |  | ||||||
| open System |  | ||||||
| open System.Collections.Generic |  | ||||||
| open System.Text.Json.Serialization |  | ||||||
| open System.Threading |  | ||||||
| open System.Threading.Tasks |  | ||||||
| open RestEase |  | ||||||
|  |  | ||||||
| /// Extension methods for constructing a REST client. |  | ||||||
| [<AutoOpen>] |  | ||||||
| module VaultClientExtensionMethodHttpClientExtension = |  | ||||||
|     /// Extension methods for HTTP clients |  | ||||||
|     type VaultClientExtensionMethod with |  | ||||||
|  |  | ||||||
|         /// Create a REST client. |  | ||||||
|         static member make (client : System.Net.Http.HttpClient) : IVaultClientExtensionMethod = |  | ||||||
|             { new IVaultClientExtensionMethod with |  | ||||||
|                 member _.GetSecret |  | ||||||
|                     (jwt : JwtVaultResponse, path : string, mountPoint : string, ct : CancellationToken option) |  | ||||||
|                     = |  | ||||||
|                     async { |  | ||||||
|                         let! ct = Async.CancellationToken |  | ||||||
|  |  | ||||||
|                         let uri = |  | ||||||
|                             System.Uri ( |  | ||||||
|                                 (match client.BaseAddress with |  | ||||||
|                                  | null -> |  | ||||||
|                                      raise ( |  | ||||||
|                                          System.ArgumentNullException ( |  | ||||||
|                                              nameof (client.BaseAddress), |  | ||||||
|                                              "No base address was supplied on the type, and no BaseAddress was on the HttpClient." |  | ||||||
|                                          ) |  | ||||||
|                                      ) |  | ||||||
|                                  | v -> v), |  | ||||||
|                                 System.Uri ( |  | ||||||
|                                     "v1/{mountPoint}/{path}" |  | ||||||
|                                         .Replace("{path}", path.ToString () |> System.Web.HttpUtility.UrlEncode) |  | ||||||
|                                         .Replace ( |  | ||||||
|                                             "{mountPoint}", |  | ||||||
|                                             mountPoint.ToString () |> System.Web.HttpUtility.UrlEncode |  | ||||||
|                                         ), |  | ||||||
|                                     System.UriKind.Relative |  | ||||||
|                                 ) |  | ||||||
|                             ) |  | ||||||
|  |  | ||||||
|                         let httpMessage = |  | ||||||
|                             new System.Net.Http.HttpRequestMessage ( |  | ||||||
|                                 Method = System.Net.Http.HttpMethod.Get, |  | ||||||
|                                 RequestUri = uri |  | ||||||
|                             ) |  | ||||||
|  |  | ||||||
|                         let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask |  | ||||||
|                         let response = response.EnsureSuccessStatusCode () |  | ||||||
|                         let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                         let! jsonNode = |  | ||||||
|                             System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct) |  | ||||||
|                             |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                         return JwtSecretResponse.jsonParse jsonNode |  | ||||||
|                     } |  | ||||||
|                     |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |  | ||||||
|  |  | ||||||
|                 member _.GetJwt (role : string, jwt : string, ct : CancellationToken option) = |  | ||||||
|                     async { |  | ||||||
|                         let! ct = Async.CancellationToken |  | ||||||
|  |  | ||||||
|                         let uri = |  | ||||||
|                             System.Uri ( |  | ||||||
|                                 (match client.BaseAddress with |  | ||||||
|                                  | null -> |  | ||||||
|                                      raise ( |  | ||||||
|                                          System.ArgumentNullException ( |  | ||||||
|                                              nameof (client.BaseAddress), |  | ||||||
|                                              "No base address was supplied on the type, and no BaseAddress was on the HttpClient." |  | ||||||
|                                          ) |  | ||||||
|                                      ) |  | ||||||
|                                  | v -> v), |  | ||||||
|                                 System.Uri ("v1/auth/jwt/login", System.UriKind.Relative) |  | ||||||
|                             ) |  | ||||||
|  |  | ||||||
|                         let httpMessage = |  | ||||||
|                             new System.Net.Http.HttpRequestMessage ( |  | ||||||
|                                 Method = System.Net.Http.HttpMethod.Get, |  | ||||||
|                                 RequestUri = uri |  | ||||||
|                             ) |  | ||||||
|  |  | ||||||
|                         let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask |  | ||||||
|                         let response = response.EnsureSuccessStatusCode () |  | ||||||
|                         let! responseStream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                         let! jsonNode = |  | ||||||
|                             System.Text.Json.Nodes.JsonNode.ParseAsync (responseStream, cancellationToken = ct) |  | ||||||
|                             |> Async.AwaitTask |  | ||||||
|  |  | ||||||
|                         return JwtVaultResponse.jsonParse jsonNode |  | ||||||
|                     } |  | ||||||
|                     |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) |  | ||||||
|             } |  | ||||||
|   | |||||||
| @@ -32,27 +32,10 @@ type JsonRecordType = | |||||||
| [<WoofWare.Myriad.Plugins.JsonParse true>] | [<WoofWare.Myriad.Plugins.JsonParse true>] | ||||||
| type ToGetExtensionMethod = | type ToGetExtensionMethod = | ||||||
|     { |     { | ||||||
|         Alpha : string |         Tinker : string | ||||||
|         Bravo : System.Uri |         Tailor : int | ||||||
|         Charlie : float |         Soldier : System.Uri | ||||||
|         Delta : float32 |         Sailor : float | ||||||
|         Echo : single |  | ||||||
|         Foxtrot : double |  | ||||||
|         Golf : int64 |  | ||||||
|         Hotel : uint64 |  | ||||||
|         India : int |  | ||||||
|         Juliette : uint |  | ||||||
|         Kilo : int32 |  | ||||||
|         Lima : uint32 |  | ||||||
|         Mike : int16 |  | ||||||
|         November : uint16 |  | ||||||
|         Oscar : int8 |  | ||||||
|         Papa : uint8 |  | ||||||
|         Quebec : byte |  | ||||||
|         Tango : sbyte |  | ||||||
|         Uniform : decimal |  | ||||||
|         Victor : char |  | ||||||
|         Whiskey : bigint |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] | [<RequireQualifiedAccess>] | ||||||
|   | |||||||
| @@ -50,7 +50,7 @@ module MyListCata = | |||||||
|                                }) -> |                                }) -> | ||||||
|                     instructions.Add (Instruction.MyList_Cons (head)) |                     instructions.Add (Instruction.MyList_Cons (head)) | ||||||
|                     instructions.Add (Instruction.Process__MyList tail) |                     instructions.Add (Instruction.Process__MyList tail) | ||||||
|             | Instruction.MyList_Cons head -> |             | Instruction.MyList_Cons (head) -> | ||||||
|                 let tail = myListStack.[myListStack.Count - 1] |                 let tail = myListStack.[myListStack.Count - 1] | ||||||
|                 myListStack.RemoveAt (myListStack.Count - 1) |                 myListStack.RemoveAt (myListStack.Count - 1) | ||||||
|                 cata.MyList.Cons head tail |> myListStack.Add |                 cata.MyList.Cons head tail |> myListStack.Add | ||||||
| @@ -103,7 +103,7 @@ module MyList2Cata = | |||||||
|                 | MyList2.Cons (arg0_0, arg1_0) -> |                 | MyList2.Cons (arg0_0, arg1_0) -> | ||||||
|                     instructions.Add (Instruction.MyList2_Cons (arg0_0)) |                     instructions.Add (Instruction.MyList2_Cons (arg0_0)) | ||||||
|                     instructions.Add (Instruction.Process__MyList2 arg1_0) |                     instructions.Add (Instruction.Process__MyList2 arg1_0) | ||||||
|             | Instruction.MyList2_Cons arg0_0 -> |             | Instruction.MyList2_Cons (arg0_0) -> | ||||||
|                 let arg1_0 = myList2Stack.[myList2Stack.Count - 1] |                 let arg1_0 = myList2Stack.[myList2Stack.Count - 1] | ||||||
|                 myList2Stack.RemoveAt (myList2Stack.Count - 1) |                 myList2Stack.RemoveAt (myList2Stack.Count - 1) | ||||||
|                 cata.MyList2.Cons arg0_0 arg1_0 |> myList2Stack.Add |                 cata.MyList2.Cons arg0_0 arg1_0 |> myList2Stack.Add | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| namespace SomeNamespace | namespace SomeNamespace | ||||||
|  |  | ||||||
| open System |  | ||||||
| open WoofWare.Myriad.Plugins | open WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| [<GenerateMock>] | [<GenerateMock>] | ||||||
| @@ -42,9 +41,3 @@ type Curried<'a> = | |||||||
|     abstract Mem4 : (int * string) -> ('a * int) -> string |     abstract Mem4 : (int * string) -> ('a * int) -> string | ||||||
|     abstract Mem5 : x : int * string -> ('a * int) -> string |     abstract Mem5 : x : int * string -> ('a * int) -> string | ||||||
|     abstract Mem6 : int * string -> y : 'a * int -> string |     abstract Mem6 : int * string -> y : 'a * int -> string | ||||||
|  |  | ||||||
| [<GenerateMock>] |  | ||||||
| type TypeWithInterface = |  | ||||||
|     inherit IDisposable |  | ||||||
|     abstract Mem1 : string option -> string[] Async |  | ||||||
|     abstract Mem2 : unit -> string[] Async |  | ||||||
|   | |||||||
| @@ -17,9 +17,6 @@ type IPureGymApi = | |||||||
|     [<Get "v1/gyms/{gym_id}/attendance">] |     [<Get "v1/gyms/{gym_id}/attendance">] | ||||||
|     abstract GetGymAttendance : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<GymAttendance> |     abstract GetGymAttendance : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<GymAttendance> | ||||||
|  |  | ||||||
|     [<Get "v1/gyms/{gym_id}/attendance">] |  | ||||||
|     abstract GetGymAttendance' : [<Path("gym_id")>] gymId : int * ?ct : CancellationToken -> Task<GymAttendance> |  | ||||||
|  |  | ||||||
|     [<RestEase.GetAttribute "v1/member">] |     [<RestEase.GetAttribute "v1/member">] | ||||||
|     abstract GetMember : ?ct : CancellationToken -> Member Task |     abstract GetMember : ?ct : CancellationToken -> Member Task | ||||||
|  |  | ||||||
| @@ -41,10 +38,6 @@ type IPureGymApi = | |||||||
|     abstract GetSessions : |     abstract GetSessions : | ||||||
|         [<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions> |         [<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions> | ||||||
|  |  | ||||||
|     [<Get "/v2/gymSessions/member?foo=1">] |  | ||||||
|     abstract GetSessionsWithQuery : |  | ||||||
|         [<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions> |  | ||||||
|  |  | ||||||
|     // An example from RestEase's own docs |     // An example from RestEase's own docs | ||||||
|     [<Post "users/new">] |     [<Post "users/new">] | ||||||
|     abstract CreateUserString : [<Body>] user : string * ?ct : CancellationToken -> Task<string> |     abstract CreateUserString : [<Body>] user : string * ?ct : CancellationToken -> Task<string> | ||||||
| @@ -127,8 +120,7 @@ type internal IApiWithoutBaseAddress = | |||||||
| [<WoofWare.Myriad.Plugins.HttpClient>] | [<WoofWare.Myriad.Plugins.HttpClient>] | ||||||
| [<BasePath "foo">] | [<BasePath "foo">] | ||||||
| type IApiWithBasePath = | type IApiWithBasePath = | ||||||
|     // Example where we use the bundled attributes rather than RestEase's |     [<Get "endpoint/{param}">] | ||||||
|     [<WoofWare.Myriad.Plugins.RestEase.Get "endpoint/{param}">] |  | ||||||
|     abstract GetPathParam : [<Path "param">] parameter : string * ?cancellationToken : CancellationToken -> Task<string> |     abstract GetPathParam : [<Path "param">] parameter : string * ?cancellationToken : CancellationToken -> Task<string> | ||||||
|  |  | ||||||
| [<WoofWare.Myriad.Plugins.HttpClient>] | [<WoofWare.Myriad.Plugins.HttpClient>] | ||||||
| @@ -149,16 +141,3 @@ type IApiWithHeaders = | |||||||
|  |  | ||||||
|     [<Get "endpoint/{param}">] |     [<Get "endpoint/{param}">] | ||||||
|     abstract GetPathParam : [<Path "param">] parameter : string * ?ct : CancellationToken -> Task<string> |     abstract GetPathParam : [<Path "param">] parameter : string * ?ct : CancellationToken -> Task<string> | ||||||
|  |  | ||||||
| [<WoofWare.Myriad.Plugins.HttpClient>] |  | ||||||
| [<WoofWare.Myriad.Plugins.RestEase.Header("Header-Name", "Header-Value")>] |  | ||||||
| type IApiWithHeaders2 = |  | ||||||
|     [<WoofWare.Myriad.Plugins.RestEase.Header "X-Foo">] |  | ||||||
|     abstract SomeHeader : string |  | ||||||
|  |  | ||||||
|     [<WoofWare.Myriad.Plugins.RestEase.Header "Authorization">] |  | ||||||
|     abstract SomeOtherHeader : int |  | ||||||
|  |  | ||||||
|     [<Get "endpoint/{param}">] |  | ||||||
|     abstract GetPathParam : |  | ||||||
|         [<WoofWare.Myriad.Plugins.RestEase.Path "param">] parameter : string * ?ct : CancellationToken -> Task<string> |  | ||||||
|   | |||||||
| @@ -27,10 +27,3 @@ type JsonRecordTypeWithBoth = | |||||||
|         E : string array |         E : string array | ||||||
|         F : int[] |         F : int[] | ||||||
|     } |     } | ||||||
|  |  | ||||||
| [<WoofWare.Myriad.Plugins.JsonSerialize true>] |  | ||||||
| [<WoofWare.Myriad.Plugins.JsonParse true>] |  | ||||||
| type FirstDu = |  | ||||||
|     | EmptyCase |  | ||||||
|     | Case1 of data : string |  | ||||||
|     | Case2 of record : JsonRecordTypeWithBoth * i : int |  | ||||||
|   | |||||||
| @@ -76,33 +76,3 @@ type IVaultClient = | |||||||
|  |  | ||||||
|     [<Get "v1/auth/jwt/login">] |     [<Get "v1/auth/jwt/login">] | ||||||
|     abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse> |     abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse> | ||||||
|  |  | ||||||
| [<WoofWare.Myriad.Plugins.HttpClient false>] |  | ||||||
| type IVaultClientNonExtensionMethod = |  | ||||||
|     [<Get "v1/{mountPoint}/{path}">] |  | ||||||
|     abstract GetSecret : |  | ||||||
|         jwt : JwtVaultResponse * |  | ||||||
|         [<Path "path">] path : string * |  | ||||||
|         [<Path "mountPoint">] mountPoint : string * |  | ||||||
|         ?ct : CancellationToken -> |  | ||||||
|             Task<JwtSecretResponse> |  | ||||||
|  |  | ||||||
|     [<Get "v1/auth/jwt/login">] |  | ||||||
|     abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse> |  | ||||||
|  |  | ||||||
| [<WoofWare.Myriad.Plugins.HttpClient(true)>] |  | ||||||
| type IVaultClientExtensionMethod = |  | ||||||
|     [<Get "v1/{mountPoint}/{path}">] |  | ||||||
|     abstract GetSecret : |  | ||||||
|         jwt : JwtVaultResponse * |  | ||||||
|         [<Path "path">] path : string * |  | ||||||
|         [<Path "mountPoint">] mountPoint : string * |  | ||||||
|         ?ct : CancellationToken -> |  | ||||||
|             Task<JwtSecretResponse> |  | ||||||
|  |  | ||||||
|     [<Get "v1/auth/jwt/login">] |  | ||||||
|     abstract GetJwt : role : string * jwt : string * ?ct : CancellationToken -> Task<JwtVaultResponse> |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| type VaultClientExtensionMethod = |  | ||||||
|     static member thisClashes = 99 |  | ||||||
|   | |||||||
| @@ -143,9 +143,6 @@ module InnerTypeWithBoth = | |||||||
|         node |         node | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Also includes an *opinionated* serializer for discriminated unions. |  | ||||||
| (Any such serializer must be opinionated, because JSON does not natively model DUs.) |  | ||||||
|  |  | ||||||
| As in `JsonParse`, you can optionally supply the boolean `true` to the attribute, | As in `JsonParse`, you can optionally supply the boolean `true` to the attribute, | ||||||
| which will cause Myriad to stamp out an extension method rather than a module with the same name as the type. | which will cause Myriad to stamp out an extension method rather than a module with the same name as the type. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -60,17 +60,8 @@ type JsonParseAttribute (isExtensionMethod : bool) = | |||||||
| /// generator should apply during build. | /// generator should apply during build. | ||||||
| /// This generator is intended to replicate much of the functionality of RestEase, | /// This generator is intended to replicate much of the functionality of RestEase, | ||||||
| /// i.e. to stamp out HTTP REST clients from interfaces defining the API. | /// i.e. to stamp out HTTP REST clients from interfaces defining the API. | ||||||
| /// | type HttpClientAttribute () = | ||||||
| /// If you supply isExtensionMethod = true, you will get extension methods. |  | ||||||
| /// These can only be consumed from F#, but the benefit is that they don't use up the module name |  | ||||||
| /// (since by default we create a module called "{TypeName}"). |  | ||||||
| type HttpClientAttribute (isExtensionMethod : bool) = |  | ||||||
|     inherit Attribute () |     inherit Attribute () | ||||||
|     /// The default value of `isExtensionMethod`, the optional argument to the HttpClientAttribute constructor. |  | ||||||
|     static member DefaultIsExtensionMethod = false |  | ||||||
|  |  | ||||||
|     /// Shorthand for the "isExtensionMethod = false" constructor; see documentation there for details. |  | ||||||
|     new () = HttpClientAttribute HttpClientAttribute.DefaultIsExtensionMethod |  | ||||||
|  |  | ||||||
| /// Attribute indicating a DU type to which the "create catamorphism" Myriad | /// Attribute indicating a DU type to which the "create catamorphism" Myriad | ||||||
| /// generator should apply during build. | /// generator should apply during build. | ||||||
|   | |||||||
| @@ -1,63 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open System |  | ||||||
|  |  | ||||||
| /// Module containing duplicates of the supported RestEase attributes, in case you don't want |  | ||||||
| /// to take a dependency on RestEase. |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module RestEase = |  | ||||||
|     /// Indicates that a method represents an HTTP Get query to the specified endpoint. |  | ||||||
|     type GetAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that a method represents an HTTP Post query to the specified endpoint. |  | ||||||
|     type PostAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that a method represents an HTTP Delete query to the specified endpoint. |  | ||||||
|     type DeleteAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that a method represents an HTTP Head query to the specified endpoint. |  | ||||||
|     type HeadAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that a method represents an HTTP Options query to the specified endpoint. |  | ||||||
|     type OptionsAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that a method represents an HTTP Put query to the specified endpoint. |  | ||||||
|     type PutAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that a method represents an HTTP Patch query to the specified endpoint. |  | ||||||
|     type PatchAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that a method represents an HTTP Trace query to the specified endpoint. |  | ||||||
|     type TraceAttribute (path : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that this argument to a method is interpolated into the HTTP request at runtime |  | ||||||
|     /// by setting a query parameter (with the given name) to the value of the annotated argument. |  | ||||||
|     type QueryAttribute (paramName : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that this interface represents a REST client which accesses an API whose paths are |  | ||||||
|     /// all relative to the given address. |  | ||||||
|     type BaseAddressAttribute (addr : string) = |  | ||||||
|         inherit Attribute () |  | ||||||
|  |  | ||||||
|     /// Indicates that this interface member causes the interface to set a header with the given name, |  | ||||||
|     /// whose value is obtained whenever required by a fresh call to the interface member. |  | ||||||
|     type HeaderAttribute (header : string, value : string option) = |  | ||||||
|         inherit Attribute () |  | ||||||
|         new (header : string) = HeaderAttribute (header, None) |  | ||||||
|         new (header : string, value : string) = HeaderAttribute (header, Some value) |  | ||||||
|  |  | ||||||
|     /// Indicates that this argument to a method is interpolated into the request path at runtime |  | ||||||
|     /// by writing it into the templated string that specifies the HTTP query e.g. in the `[<Get "/foo/{template}">]`. |  | ||||||
|     type PathAttribute (path : string option) = |  | ||||||
|         inherit Attribute () |  | ||||||
|         new (path : string) = PathAttribute (Some path) |  | ||||||
|         new () = PathAttribute None |  | ||||||
| @@ -6,10 +6,7 @@ WoofWare.Myriad.Plugins.GenerateMockAttribute..ctor [constructor]: unit | |||||||
| WoofWare.Myriad.Plugins.GenerateMockAttribute.DefaultIsInternal [static property]: [read-only] bool | WoofWare.Myriad.Plugins.GenerateMockAttribute.DefaultIsInternal [static property]: [read-only] bool | ||||||
| WoofWare.Myriad.Plugins.GenerateMockAttribute.get_DefaultIsInternal [static method]: unit -> bool | WoofWare.Myriad.Plugins.GenerateMockAttribute.get_DefaultIsInternal [static method]: unit -> bool | ||||||
| WoofWare.Myriad.Plugins.HttpClientAttribute inherit System.Attribute | WoofWare.Myriad.Plugins.HttpClientAttribute inherit System.Attribute | ||||||
| WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: bool |  | ||||||
| WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: unit | WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: unit | ||||||
| WoofWare.Myriad.Plugins.HttpClientAttribute.DefaultIsExtensionMethod [static property]: [read-only] bool |  | ||||||
| WoofWare.Myriad.Plugins.HttpClientAttribute.get_DefaultIsExtensionMethod [static method]: unit -> bool |  | ||||||
| WoofWare.Myriad.Plugins.JsonParseAttribute inherit System.Attribute | WoofWare.Myriad.Plugins.JsonParseAttribute inherit System.Attribute | ||||||
| WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: bool | WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: bool | ||||||
| WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: unit | WoofWare.Myriad.Plugins.JsonParseAttribute..ctor [constructor]: unit | ||||||
| @@ -22,32 +19,3 @@ WoofWare.Myriad.Plugins.JsonSerializeAttribute.DefaultIsExtensionMethod [static | |||||||
| WoofWare.Myriad.Plugins.JsonSerializeAttribute.get_DefaultIsExtensionMethod [static method]: unit -> bool | WoofWare.Myriad.Plugins.JsonSerializeAttribute.get_DefaultIsExtensionMethod [static method]: unit -> bool | ||||||
| WoofWare.Myriad.Plugins.RemoveOptionsAttribute inherit System.Attribute | WoofWare.Myriad.Plugins.RemoveOptionsAttribute inherit System.Attribute | ||||||
| WoofWare.Myriad.Plugins.RemoveOptionsAttribute..ctor [constructor]: unit | WoofWare.Myriad.Plugins.RemoveOptionsAttribute..ctor [constructor]: unit | ||||||
| WoofWare.Myriad.Plugins.RestEase inherit obj |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+BaseAddressAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+BaseAddressAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+DeleteAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+DeleteAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+GetAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+GetAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+HeadAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+HeadAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+HeaderAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: (string, string option) |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: (string, string) |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+OptionsAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+OptionsAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PatchAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PatchAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PathAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: string option |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: unit |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PostAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PostAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PutAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+PutAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+QueryAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+QueryAttribute..ctor [constructor]: string |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+TraceAttribute inherit System.Attribute |  | ||||||
| WoofWare.Myriad.Plugins.RestEase+TraceAttribute..ctor [constructor]: string |  | ||||||
| @@ -11,9 +11,11 @@ module TestSurface = | |||||||
|     [<Test>] |     [<Test>] | ||||||
|     let ``Ensure API surface has not been modified`` () = ApiSurface.assertIdentical assembly |     let ``Ensure API surface has not been modified`` () = ApiSurface.assertIdentical assembly | ||||||
|  |  | ||||||
|  |     (* | ||||||
|     [<Test>] |     [<Test>] | ||||||
|     let ``Check version against remote`` () = |     let ``Check version against remote`` () = | ||||||
|         MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins.Attributes" |         MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins.Attributes" | ||||||
|  |     *) | ||||||
|  |  | ||||||
|     [<Test ; Explicit>] |     [<Test ; Explicit>] | ||||||
|     let ``Update API surface`` () = |     let ``Update API surface`` () = | ||||||
|   | |||||||
| @@ -12,9 +12,9 @@ | |||||||
|     </ItemGroup> |     </ItemGroup> | ||||||
|  |  | ||||||
|     <ItemGroup> |     <ItemGroup> | ||||||
|         <PackageReference Include="ApiSurface" Version="4.0.40" /> |         <PackageReference Include="ApiSurface" Version="4.0.28" /> | ||||||
|         <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/> |         <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0"/> | ||||||
|         <PackageReference Include="NUnit" Version="4.1.0"/> |         <PackageReference Include="NUnit" Version="3.13.3"/> | ||||||
|         <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> |         <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> | ||||||
|     </ItemGroup> |     </ItemGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,7 +19,6 @@ | |||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Compile Include="Attributes.fs"/> |     <Compile Include="Attributes.fs"/> | ||||||
|     <Compile Include="RestEase.fs" /> |  | ||||||
|     <EmbeddedResource Include="version.json"/> |     <EmbeddedResource Include="version.json"/> | ||||||
|     <EmbeddedResource Include="SurfaceBaseline.txt"/> |     <EmbeddedResource Include="SurfaceBaseline.txt"/> | ||||||
|     <None Include="..\README.md"> |     <None Include="..\README.md"> | ||||||
|   | |||||||
| @@ -1,15 +1,7 @@ | |||||||
| { | { | ||||||
|   "version": "3.1", |   "version": "2.2", | ||||||
|   "publicReleaseRefSpec": [ |   "publicReleaseRefSpec": [ | ||||||
|     "^refs/heads/main$" |     "^refs/heads/main$" | ||||||
|   ], |   ], | ||||||
|   "pathFilters": [ |   "pathFilters": null | ||||||
|     ":/README.md", |  | ||||||
|     ":/LICENSE", |  | ||||||
|     ":/WoofWare.Myriad.Plugins/logo.png", |  | ||||||
|     ":/Directory.Build.props", |  | ||||||
|     ":/global.json", |  | ||||||
|     "./", |  | ||||||
|     "^./Test" |  | ||||||
|   ] |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -89,7 +89,6 @@ module TestPureGymRestApi = | |||||||
|         let api = PureGymApi.make client |         let api = PureGymApi.make client | ||||||
|  |  | ||||||
|         api.GetGymAttendance(requestedGym).Result |> shouldEqual expected |         api.GetGymAttendance(requestedGym).Result |> shouldEqual expected | ||||||
|         api.GetGymAttendance'(requestedGym).Result |> shouldEqual expected |  | ||||||
|  |  | ||||||
|     let memberCases = |     let memberCases = | ||||||
|         PureGymDtos.memberCases |> List.allPairs baseUris |> List.map TestCaseData |         PureGymDtos.memberCases |> List.allPairs baseUris |> List.map TestCaseData | ||||||
| @@ -235,33 +234,6 @@ module TestPureGymRestApi = | |||||||
|  |  | ||||||
|         api.GetSessions(startDate, endDate).Result |> shouldEqual expected |         api.GetSessions(startDate, endDate).Result |> shouldEqual expected | ||||||
|  |  | ||||||
|     [<TestCaseSource(nameof sessionsCases)>] |  | ||||||
|     let ``Test GetSessionsWithQuery`` |  | ||||||
|         (baseUri : Uri, (startDate : DateOnly, (endDate : DateOnly, (json : string, expected : Sessions)))) |  | ||||||
|         = |  | ||||||
|         let proc (message : HttpRequestMessage) : HttpResponseMessage Async = |  | ||||||
|             async { |  | ||||||
|                 message.Method |> shouldEqual HttpMethod.Get |  | ||||||
|  |  | ||||||
|                 // This one is specified as being absolute, in its attribute on the IPureGymApi type |  | ||||||
|                 let expectedUri = |  | ||||||
|                     let fromDate = dateOnlyToString startDate |  | ||||||
|                     let toDate = dateOnlyToString endDate |  | ||||||
|                     $"https://example.com/v2/gymSessions/member?foo=1&fromDate=%s{fromDate}&toDate=%s{toDate}" |  | ||||||
|  |  | ||||||
|                 message.RequestUri.ToString () |> shouldEqual expectedUri |  | ||||||
|  |  | ||||||
|                 let content = new StringContent (json) |  | ||||||
|                 let resp = new HttpResponseMessage (HttpStatusCode.OK) |  | ||||||
|                 resp.Content <- content |  | ||||||
|                 return resp |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         use client = HttpClientMock.make baseUri proc |  | ||||||
|         let api = PureGymApi.make client |  | ||||||
|  |  | ||||||
|         api.GetSessionsWithQuery(startDate, endDate).Result |> shouldEqual expected |  | ||||||
|  |  | ||||||
|     [<Test>] |     [<Test>] | ||||||
|     let ``URI example`` () = |     let ``URI example`` () = | ||||||
|         let proc (message : HttpRequestMessage) : HttpResponseMessage Async = |         let proc (message : HttpRequestMessage) : HttpResponseMessage Async = | ||||||
|   | |||||||
| @@ -87,10 +87,8 @@ module TestVaultClient = | |||||||
|     } |     } | ||||||
| }""" | }""" | ||||||
|  |  | ||||||
|     [<TestCase 1>] |     [<Test>] | ||||||
|     [<TestCase 2>] |     let ``URI example`` () = | ||||||
|     [<TestCase 3>] |  | ||||||
|     let ``URI example`` (vaultClientId : int) = |  | ||||||
|         let proc (message : HttpRequestMessage) : HttpResponseMessage Async = |         let proc (message : HttpRequestMessage) : HttpResponseMessage Async = | ||||||
|             async { |             async { | ||||||
|                 message.Method |> shouldEqual HttpMethod.Get |                 message.Method |> shouldEqual HttpMethod.Get | ||||||
| @@ -114,25 +112,10 @@ module TestVaultClient = | |||||||
|             } |             } | ||||||
|  |  | ||||||
|         use client = HttpClientMock.make (Uri "https://my-vault.com") proc |         use client = HttpClientMock.make (Uri "https://my-vault.com") proc | ||||||
|  |  | ||||||
|         let value = |  | ||||||
|             match vaultClientId with |  | ||||||
|             | 1 -> |  | ||||||
|         let api = VaultClient.make client |         let api = VaultClient.make client | ||||||
|  |  | ||||||
|         let vaultResponse = api.GetJwt("role", "jwt").Result |         let vaultResponse = api.GetJwt("role", "jwt").Result | ||||||
|         let value = api.GetSecret(vaultResponse, "path", "mount").Result |         let value = api.GetSecret(vaultResponse, "path", "mount").Result | ||||||
|                 value |  | ||||||
|             | 2 -> |  | ||||||
|                 let api = VaultClientNonExtensionMethod.make client |  | ||||||
|                 let vaultResponse = api.GetJwt("role", "jwt").Result |  | ||||||
|                 let value = api.GetSecret(vaultResponse, "path", "mount").Result |  | ||||||
|                 value |  | ||||||
|             | 3 -> |  | ||||||
|                 let api = VaultClientExtensionMethod.make client |  | ||||||
|                 let vaultResponse = api.GetJwt("role", "jwt").Result |  | ||||||
|                 let value = api.GetSecret(vaultResponse, "path", "mount").Result |  | ||||||
|                 value |  | ||||||
|             | _ -> failwith $"Unrecognised ID: %i{vaultClientId}" |  | ||||||
|  |  | ||||||
|         value.Data |         value.Data | ||||||
|         |> Seq.toList |         |> Seq.toList | ||||||
| @@ -185,5 +168,3 @@ module TestVaultClient = | |||||||
|                 "key8_1", "https://example.com/data8/1" |                 "key8_1", "https://example.com/data8/1" | ||||||
|                 "key8_2", "https://example.com/data8/2" |                 "key8_2", "https://example.com/data8/2" | ||||||
|             ] |             ] | ||||||
|  |  | ||||||
|     let _canSeePastExtensionMethod = VaultClientExtensionMethod.thisClashes |  | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
| namespace WoofWare.Myriad.Plugins.Test | namespace WoofWare.Myriad.Plugins.Test | ||||||
|  |  | ||||||
| open System | open System | ||||||
| open System.Numerics |  | ||||||
| open System.Text.Json.Nodes | open System.Text.Json.Nodes | ||||||
| open ConsumePlugin | open ConsumePlugin | ||||||
| open NUnit.Framework | open NUnit.Framework | ||||||
| @@ -13,62 +12,15 @@ module TestExtensionMethod = | |||||||
|     [<Test>] |     [<Test>] | ||||||
|     let ``Parse via extension method`` () = |     let ``Parse via extension method`` () = | ||||||
|         let json = |         let json = | ||||||
|             """{ |             """{"tinker": "job", "tailor": 3, "soldier": "https://example.com", "sailor": 3.1}""" | ||||||
|     "alpha": "hello!", |  | ||||||
|     "bravo": "https://example.com", |  | ||||||
|     "charlie": 0.3341, |  | ||||||
|     "delta": 110033.4, |  | ||||||
|     "echo": -0.000993, |  | ||||||
|     "foxtrot": -999999999999, |  | ||||||
|     "golf": -123456789101112, |  | ||||||
|     "hotel": 18446744073709551615, |  | ||||||
|     "india": 99884, |  | ||||||
|     "juliette": 12223334, |  | ||||||
|     "kilo": -2147483642, |  | ||||||
|     "lima": 4294967293, |  | ||||||
|     "mike": -32767, |  | ||||||
|     "november": 65533, |  | ||||||
|     "oscar": -125, |  | ||||||
|     "papa": 253, |  | ||||||
|     "quebec": 254, |  | ||||||
|     "tango": -3, |  | ||||||
|     "uniform": 1004443.300988393349583009, |  | ||||||
|     "victor": "x", |  | ||||||
|     "whiskey": 123456123456123456123456123456123456123456 |  | ||||||
| }""" |  | ||||||
|             |> JsonNode.Parse |             |> JsonNode.Parse | ||||||
|  |  | ||||||
|         let expected = |         let expected = | ||||||
|             { |             { | ||||||
|                 Alpha = "hello!" |                 Tinker = "job" | ||||||
|                 Bravo = Uri "https://example.com" |                 Tailor = 3 | ||||||
|                 Charlie = 0.3341 |                 Soldier = Uri "https://example.com" | ||||||
|                 Delta = 110033.4f |                 Sailor = 3.1 | ||||||
|                 Echo = -0.000993f |  | ||||||
|                 Foxtrot = -999999999999.0 |  | ||||||
|                 Golf = -123456789101112L |  | ||||||
|                 Hotel = 18446744073709551615UL |  | ||||||
|                 India = 99884 |  | ||||||
|                 Juliette = 12223334u |  | ||||||
|                 Kilo = -2147483642 |  | ||||||
|                 Lima = 4294967293u |  | ||||||
|                 Mike = -32767s |  | ||||||
|                 November = 65533us |  | ||||||
|                 Oscar = -125y |  | ||||||
|                 Papa = 253uy |  | ||||||
|                 Quebec = 254uy |  | ||||||
|                 Tango = -3y |  | ||||||
|                 Uniform = 1004443.300988393349583009m |  | ||||||
|                 Victor = 'x' |  | ||||||
|                 Whiskey = |  | ||||||
|                     let mutable i = BigInteger 0 |  | ||||||
|  |  | ||||||
|                     for _ = 0 to 6 do |  | ||||||
|                         i <- i * BigInteger 1000000 + BigInteger 123456 |  | ||||||
|  |  | ||||||
|                     i |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         let actual = ToGetExtensionMethod.jsonParse json |         ToGetExtensionMethod.jsonParse json |> shouldEqual expected | ||||||
|  |  | ||||||
|         actual |> shouldEqual expected |  | ||||||
|   | |||||||
| @@ -7,8 +7,6 @@ open FsUnitTyped | |||||||
|  |  | ||||||
| [<TestFixture>] | [<TestFixture>] | ||||||
| module TestJsonParse = | module TestJsonParse = | ||||||
|     let _canSeePastExtensionMethod = ToGetExtensionMethod.thisModuleWouldClash |  | ||||||
|  |  | ||||||
|     [<Test>] |     [<Test>] | ||||||
|     let ``Single example`` () = |     let ``Single example`` () = | ||||||
|         let s = |         let s = | ||||||
|   | |||||||
| @@ -2,9 +2,10 @@ namespace WoofWare.Myriad.Plugins.Test | |||||||
|  |  | ||||||
| open System | open System | ||||||
| open System.Collections.Generic | open System.Collections.Generic | ||||||
|  | open System.IO | ||||||
|  | open System.Text | ||||||
|  | open System.Text.Json | ||||||
| open System.Text.Json.Nodes | open System.Text.Json.Nodes | ||||||
| open FsCheck.Random |  | ||||||
| open Microsoft.FSharp.Reflection |  | ||||||
| open NUnit.Framework | open NUnit.Framework | ||||||
| open FsCheck | open FsCheck | ||||||
| open FsUnitTyped | open FsUnitTyped | ||||||
| @@ -123,83 +124,3 @@ module TestJsonSerde = | |||||||
|         |> shouldEqual ( |         |> shouldEqual ( | ||||||
|             sprintf """{"it\u0027s-a-me":"%s","map":{},"readOnlyDict":{},"dict":{},"concreteDict":{}}""" guidStr |             sprintf """{"it\u0027s-a-me":"%s","map":{},"readOnlyDict":{},"dict":{},"concreteDict":{}}""" guidStr | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     type Generators = |  | ||||||
|         static member TestCase () = |  | ||||||
|             { new Arbitrary<InnerTypeWithBoth>() with |  | ||||||
|                 override x.Generator = innerGen 5 |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|     let sanitiseInner (r : InnerTypeWithBoth) : InnerTypeWithBoth = |  | ||||||
|         { |  | ||||||
|             Thing = r.Thing |  | ||||||
|             Map = r.Map |  | ||||||
|             ReadOnlyDict = r.ReadOnlyDict |  | ||||||
|             Dict = r.Dict |  | ||||||
|             ConcreteDict = r.ConcreteDict |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let sanitiseRec (r : JsonRecordTypeWithBoth) : JsonRecordTypeWithBoth = |  | ||||||
|         { |  | ||||||
|             A = r.A |  | ||||||
|             B = if isNull r.B then "<null>" else r.B |  | ||||||
|             C = |  | ||||||
|                 if Object.ReferenceEquals (r.C, (null : obj)) then |  | ||||||
|                     [] |  | ||||||
|                 else |  | ||||||
|                     r.C |  | ||||||
|             D = sanitiseInner r.D |  | ||||||
|             E = if isNull r.E then [||] else r.E |  | ||||||
|             F = |  | ||||||
|                 if Object.ReferenceEquals (r.F, (null : obj)) then |  | ||||||
|                     [||] |  | ||||||
|                 else |  | ||||||
|                     r.F |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let duGen = |  | ||||||
|         gen { |  | ||||||
|             let! case = Gen.choose (0, 2) |  | ||||||
|  |  | ||||||
|             match case with |  | ||||||
|             | 0 -> return FirstDu.EmptyCase |  | ||||||
|             | 1 -> |  | ||||||
|                 let! s = Arb.generate<NonNull<string>> |  | ||||||
|                 return FirstDu.Case1 s.Get |  | ||||||
|             | 2 -> |  | ||||||
|                 let! i = Arb.generate<int> |  | ||||||
|                 let! record = outerGen |  | ||||||
|                 return FirstDu.Case2 (record, i) |  | ||||||
|             | _ -> return failwith $"unexpected: %i{case}" |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     [<Test>] |  | ||||||
|     let ``Discriminated union works`` () = |  | ||||||
|         let property (du : FirstDu) : unit = |  | ||||||
|             du |  | ||||||
|             |> FirstDu.toJsonNode |  | ||||||
|             |> fun s -> s.ToJsonString () |  | ||||||
|             |> JsonNode.Parse |  | ||||||
|             |> FirstDu.jsonParse |  | ||||||
|             |> shouldEqual du |  | ||||||
|  |  | ||||||
|         property |> Prop.forAll (Arb.fromGen duGen) |> Check.QuickThrowOnFailure |  | ||||||
|  |  | ||||||
|     [<Test>] |  | ||||||
|     let ``DU generator covers all cases`` () = |  | ||||||
|         let rand = Random () |  | ||||||
|         let cases = FSharpType.GetUnionCases typeof<FirstDu> |  | ||||||
|         let counts = Array.zeroCreate<int> cases.Length |  | ||||||
|  |  | ||||||
|         let decompose = FSharpValue.PreComputeUnionTagReader typeof<FirstDu> |  | ||||||
|  |  | ||||||
|         let mutable i = 0 |  | ||||||
|  |  | ||||||
|         while i < 10_000 && Array.exists (fun i -> i = 0) counts do |  | ||||||
|             let du = Gen.eval 10 (StdGen.StdGen (rand.Next (), rand.Next ())) duGen |  | ||||||
|             let tag = decompose du |  | ||||||
|             counts.[tag] <- counts.[tag] + 1 |  | ||||||
|             i <- i + 1 |  | ||||||
|  |  | ||||||
|         for i in counts do |  | ||||||
|             i |> shouldBeGreaterThan 0 |  | ||||||
|   | |||||||
| @@ -12,8 +12,7 @@ module TestSurface = | |||||||
|     let ``Ensure API surface has not been modified`` () = ApiSurface.assertIdentical assembly |     let ``Ensure API surface has not been modified`` () = ApiSurface.assertIdentical assembly | ||||||
|  |  | ||||||
|     [<Test>] |     [<Test>] | ||||||
|     // https://github.com/nunit/nunit3-vs-adapter/issues/876 |     let ``Check version against remote`` () = | ||||||
|     let CheckVersionAgainstRemote () = |  | ||||||
|         MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins" |         MonotonicVersion.validate assembly "WoofWare.Myriad.Plugins" | ||||||
|  |  | ||||||
|     [<Test ; Explicit>] |     [<Test ; Explicit>] | ||||||
|   | |||||||
| @@ -33,12 +33,13 @@ | |||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="ApiSurface" Version="4.0.40"/> |     <PackageReference Include="ApiSurface" Version="4.0.28"/> | ||||||
|     <PackageReference Include="FsCheck" Version="2.16.6"/> |     <PackageReference Include="FsCheck" Version="2.16.6"/> | ||||||
|     <PackageReference Include="FsUnit" Version="6.0.0"/> |     <PackageReference Include="FsUnit" Version="6.0.0"/> | ||||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/> |     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/> | ||||||
|     <PackageReference Include="NUnit" Version="4.1.0"/> |     <PackageReference Include="NUnit" Version="4.0.1"/> | ||||||
|     <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> |     <PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/> | ||||||
|  |     <PackageReference Include="coverlet.collector" Version="6.0.0"/> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| namespace WoofWare.Myriad.Plugins | namespace WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax | open Fantomas.FCS.Syntax | ||||||
|  | open Fantomas.FCS.SyntaxTrivia | ||||||
| open Fantomas.FCS.Text.Range | open Fantomas.FCS.Text.Range | ||||||
| open Fantomas.FCS.Xml | open Fantomas.FCS.Xml | ||||||
|  | open Myriad.Core.AstExtensions | ||||||
|  |  | ||||||
| type internal ParameterInfo = | type internal ParameterInfo = | ||||||
|     { |     { | ||||||
| @@ -52,7 +54,6 @@ type internal InterfaceType = | |||||||
|     { |     { | ||||||
|         Attributes : SynAttribute list |         Attributes : SynAttribute list | ||||||
|         Name : LongIdent |         Name : LongIdent | ||||||
|         Inherits : SynType list |  | ||||||
|         Members : MemberInfo list |         Members : MemberInfo list | ||||||
|         Properties : PropertyInfo list |         Properties : PropertyInfo list | ||||||
|         Generics : SynTyparDecls option |         Generics : SynTyparDecls option | ||||||
| @@ -104,17 +105,81 @@ module internal AstHelper = | |||||||
|         SynExpr.Record (None, None, fields, range0) |         SynExpr.Record (None, None, fields, range0) | ||||||
|  |  | ||||||
|     let defineRecordType (record : RecordType) : SynTypeDefn = |     let defineRecordType (record : RecordType) : SynTypeDefn = | ||||||
|         let name = |         let repr = | ||||||
|             SynComponentInfo.create record.Name |             SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, Seq.toList record.Fields, range0), range0) | ||||||
|             |> SynComponentInfo.setAccessibility record.Accessibility |  | ||||||
|             |> match record.XmlDoc with |  | ||||||
|                | None -> id |  | ||||||
|                | Some doc -> SynComponentInfo.withDocString doc |  | ||||||
|             |> SynComponentInfo.setGenerics record.Generics |  | ||||||
|  |  | ||||||
|         SynTypeDefnRepr.record (Seq.toList record.Fields) |         let name = | ||||||
|         |> SynTypeDefn.create name |             SynComponentInfo.Create ( | ||||||
|         |> SynTypeDefn.withMemberDefns (defaultArg record.Members SynMemberDefns.Empty) |                 [ record.Name ], | ||||||
|  |                 ?xmldoc = record.XmlDoc, | ||||||
|  |                 ?parameters = record.Generics, | ||||||
|  |                 access = record.Accessibility | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         let trivia : SynTypeDefnTrivia = | ||||||
|  |             { | ||||||
|  |                 LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0 | ||||||
|  |                 EqualsRange = Some range0 | ||||||
|  |                 WithKeyword = Some range0 | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         SynTypeDefn (name, repr, defaultArg record.Members SynMemberDefns.Empty, None, range0, trivia) | ||||||
|  |  | ||||||
|  |     let isOptionIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent with | ||||||
|  |         | [ i ] when System.String.Equals (i.idText, "option", System.StringComparison.OrdinalIgnoreCase) -> true | ||||||
|  |         // TODO: consider Microsoft.FSharp.Option or whatever it is | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|  |     let isListIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent with | ||||||
|  |         | [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true | ||||||
|  |         // TODO: consider FSharpList or whatever it is | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|  |     let isArrayIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent with | ||||||
|  |         | [ i ] when | ||||||
|  |             System.String.Equals (i.idText, "array", System.StringComparison.OrdinalIgnoreCase) | ||||||
|  |             || System.String.Equals (i.idText, "[]", System.StringComparison.Ordinal) | ||||||
|  |             -> | ||||||
|  |             true | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|  |     let isResponseIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent |> List.map _.idText with | ||||||
|  |         | [ "Response" ] | ||||||
|  |         | [ "RestEase" ; "Response" ] -> true | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|  |     let isMapIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent |> List.map _.idText with | ||||||
|  |         | [ "Map" ] -> true | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|  |     let isReadOnlyDictionaryIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent |> List.map _.idText with | ||||||
|  |         | [ "IReadOnlyDictionary" ] | ||||||
|  |         | [ "Generic" ; "IReadOnlyDictionary" ] | ||||||
|  |         | [ "Collections" ; "Generic" ; "IReadOnlyDictionary" ] | ||||||
|  |         | [ "System" ; "Collections" ; "Generic" ; "IReadOnlyDictionary" ] -> true | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|  |     let isDictionaryIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent |> List.map _.idText with | ||||||
|  |         | [ "Dictionary" ] | ||||||
|  |         | [ "Generic" ; "Dictionary" ] | ||||||
|  |         | [ "Collections" ; "Generic" ; "Dictionary" ] | ||||||
|  |         | [ "System" ; "Collections" ; "Generic" ; "Dictionary" ] -> true | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|  |     let isIDictionaryIdent (ident : SynLongIdent) : bool = | ||||||
|  |         match ident.LongIdent |> List.map _.idText with | ||||||
|  |         | [ "IDictionary" ] | ||||||
|  |         | [ "Generic" ; "IDictionary" ] | ||||||
|  |         | [ "Collections" ; "Generic" ; "IDictionary" ] | ||||||
|  |         | [ "System" ; "Collections" ; "Generic" ; "IDictionary" ] -> true | ||||||
|  |         | _ -> false | ||||||
|  |  | ||||||
|     let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list = |     let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list = | ||||||
|         moduleDecls |         moduleDecls | ||||||
| @@ -136,12 +201,12 @@ module internal AstHelper = | |||||||
|         | SynType.Paren (inner, _) -> |         | SynType.Paren (inner, _) -> | ||||||
|             let result, _ = convertSigParam inner |             let result, _ = convertSigParam inner | ||||||
|             result, true |             result, true | ||||||
|         | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> |         | SynType.LongIdent ident -> | ||||||
|             { |             { | ||||||
|                 Attributes = [] |                 Attributes = [] | ||||||
|                 IsOptional = false |                 IsOptional = false | ||||||
|                 Id = None |                 Id = None | ||||||
|                 Type = SynType.createLongIdent ident |                 Type = SynType.CreateLongIdent ident | ||||||
|             }, |             }, | ||||||
|             false |             false | ||||||
|         | SynType.SignatureParameter (attrs, opt, id, usedType, _) -> |         | SynType.SignatureParameter (attrs, opt, id, usedType, _) -> | ||||||
| @@ -159,7 +224,7 @@ module internal AstHelper = | |||||||
|                 Attributes = [] |                 Attributes = [] | ||||||
|                 IsOptional = false |                 IsOptional = false | ||||||
|                 Id = None |                 Id = None | ||||||
|                 Type = SynType.var typar |                 Type = SynType.Var (typar, range0) | ||||||
|             }, |             }, | ||||||
|             false |             false | ||||||
|         | _ -> failwithf "expected SignatureParameter, got: %+A" ty |         | _ -> failwithf "expected SignatureParameter, got: %+A" ty | ||||||
| @@ -188,6 +253,10 @@ module internal AstHelper = | |||||||
|             } |             } | ||||||
|         | _ -> failwithf "Didn't have alternating type-and-star in interface member definition: %+A" tupleType |         | _ -> failwithf "Didn't have alternating type-and-star in interface member definition: %+A" tupleType | ||||||
|  |  | ||||||
|  |     let toFun (inputs : SynType list) (ret : SynType) : SynType = | ||||||
|  |         (ret, List.rev inputs) | ||||||
|  |         ||> List.fold (fun ty input -> SynType.CreateFun (input, ty)) | ||||||
|  |  | ||||||
|     /// Returns the args (where these are tuple types if curried) in order, and the return type. |     /// Returns the args (where these are tuple types if curried) in order, and the return type. | ||||||
|     let rec getType (ty : SynType) : (SynType * bool) list * SynType = |     let rec getType (ty : SynType) : (SynType * bool) list * SynType = | ||||||
|         match ty with |         match ty with | ||||||
| @@ -200,7 +269,7 @@ module internal AstHelper = | |||||||
|                 | SynType.Paren (argType, _) -> getType argType, true |                 | SynType.Paren (argType, _) -> getType argType, true | ||||||
|                 | _ -> getType argType, false |                 | _ -> getType argType, false | ||||||
|  |  | ||||||
|             ((SynType.toFun (List.map fst inputArgs) inputRet), hasParen) :: args, ret |             ((toFun (List.map fst inputArgs) inputRet), hasParen) :: args, ret | ||||||
|         | _ -> [], ty |         | _ -> [], ty | ||||||
|  |  | ||||||
|     let private parseMember (slotSig : SynValSig) (flags : SynMemberFlags) : Choice<MemberInfo, PropertyInfo> = |     let private parseMember (slotSig : SynValSig) (flags : SynMemberFlags) : Choice<MemberInfo, PropertyInfo> = | ||||||
| @@ -257,7 +326,7 @@ module internal AstHelper = | |||||||
|                                     Attributes = [] |                                     Attributes = [] | ||||||
|                                     IsOptional = false |                                     IsOptional = false | ||||||
|                                     Id = None |                                     Id = None | ||||||
|                                     Type = SynType.createLongIdent ident |                                     Type = SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent ident) | ||||||
|                                 } |                                 } | ||||||
|                                 |> List.singleton |                                 |> List.singleton | ||||||
|                         } |                         } | ||||||
| @@ -269,22 +338,11 @@ module internal AstHelper = | |||||||
|                                     Attributes = [] |                                     Attributes = [] | ||||||
|                                     IsOptional = false |                                     IsOptional = false | ||||||
|                                     Id = None |                                     Id = None | ||||||
|                                     Type = SynType.var typar |                                     Type = SynType.Var (typar, range0) | ||||||
|                                 } |  | ||||||
|                                 |> List.singleton |  | ||||||
|                         } |  | ||||||
|                     | arg -> |  | ||||||
|                         { |  | ||||||
|                             HasParen = false |  | ||||||
|                             Args = |  | ||||||
|                                 { |  | ||||||
|                                     Attributes = [] |  | ||||||
|                                     IsOptional = false |  | ||||||
|                                     Id = None |  | ||||||
|                                     Type = arg |  | ||||||
|                                 } |                                 } | ||||||
|                                 |> List.singleton |                                 |> List.singleton | ||||||
|                         } |                         } | ||||||
|  |                     | _ -> failwith $"Unrecognised args in interface method declaration: %+A{args}" | ||||||
|                     |> fun ty -> |                     |> fun ty -> | ||||||
|                         { ty with |                         { ty with | ||||||
|                             HasParen = ty.HasParen || hasParen |                             HasParen = ty.HasParen || hasParen | ||||||
| @@ -328,26 +386,22 @@ module internal AstHelper = | |||||||
|  |  | ||||||
|         let attrs = attrs |> List.collect (fun s -> s.Attributes) |         let attrs = attrs |> List.collect (fun s -> s.Attributes) | ||||||
|  |  | ||||||
|         let members, inherits = |         let members, properties = | ||||||
|             match synTypeDefnRepr with |             match synTypeDefnRepr with | ||||||
|             | SynTypeDefnRepr.ObjectModel (_kind, members, _) -> |             | SynTypeDefnRepr.ObjectModel (_kind, members, _) -> | ||||||
|                 members |                 members | ||||||
|                 |> List.map (fun defn -> |                 |> List.map (fun defn -> | ||||||
|                     match defn with |                     match defn with | ||||||
|                     | SynMemberDefn.AbstractSlot (slotSig, flags, _, _) -> Choice1Of2 (parseMember slotSig flags) |                     | SynMemberDefn.AbstractSlot (slotSig, flags, _, _) -> parseMember slotSig flags | ||||||
|                     | SynMemberDefn.Inherit (baseType, _asIdent, _) -> Choice2Of2 baseType |  | ||||||
|                     | _ -> failwith $"Unrecognised member definition: %+A{defn}" |                     | _ -> failwith $"Unrecognised member definition: %+A{defn}" | ||||||
|                 ) |                 ) | ||||||
|             | _ -> failwith $"Unrecognised SynTypeDefnRepr for an interface type: %+A{synTypeDefnRepr}" |             | _ -> failwith $"Unrecognised SynTypeDefnRepr for an interface type: %+A{synTypeDefnRepr}" | ||||||
|             |> List.partitionChoice |             |> List.partitionChoice | ||||||
|  |  | ||||||
|         let members, properties = members |> List.partitionChoice |  | ||||||
|  |  | ||||||
|         { |         { | ||||||
|             Members = members |             Members = members | ||||||
|             Properties = properties |             Properties = properties | ||||||
|             Name = interfaceName |             Name = interfaceName | ||||||
|             Inherits = inherits |  | ||||||
|             Attributes = attrs |             Attributes = attrs | ||||||
|             Generics = typars |             Generics = typars | ||||||
|             Accessibility = accessibility |             Accessibility = accessibility | ||||||
| @@ -423,3 +477,176 @@ module internal AstHelper = | |||||||
|                 } |                 } | ||||||
|             ) |             ) | ||||||
|         | _ -> failwithf "Failed to get record elements for type that was: %+A" repr |         | _ -> failwithf "Failed to get record elements for type that was: %+A" repr | ||||||
|  |  | ||||||
|  | [<AutoOpen>] | ||||||
|  | module internal SynTypePatterns = | ||||||
|  |     let (|OptionType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isOptionIdent ident -> | ||||||
|  |             Some innerType | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|ListType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isListIdent ident -> | ||||||
|  |             Some innerType | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|ArrayType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isArrayIdent ident -> | ||||||
|  |             Some innerType | ||||||
|  |         | SynType.Array (1, innerType, _) -> Some innerType | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|RestEaseResponseType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when AstHelper.isResponseIdent ident -> | ||||||
|  |             Some innerType | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|DictionaryType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isDictionaryIdent ident -> | ||||||
|  |             Some (key, value) | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|IDictionaryType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isIDictionaryIdent ident -> | ||||||
|  |             Some (key, value) | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|IReadOnlyDictionaryType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when | ||||||
|  |             AstHelper.isReadOnlyDictionaryIdent ident | ||||||
|  |             -> | ||||||
|  |             Some (key, value) | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|MapType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when AstHelper.isMapIdent ident -> | ||||||
|  |             Some (key, value) | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     /// Returns the string name of the type. | ||||||
|  |     let (|PrimitiveType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent with | ||||||
|  |             | [ i ] -> | ||||||
|  |                 [ "string" ; "float" ; "int" ; "bool" ; "char" ] | ||||||
|  |                 |> List.tryFind (fun s -> s = i.idText) | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|String|_|) (fieldType : SynType) : unit option = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent with | ||||||
|  |             | [ i ] -> | ||||||
|  |                 [ "string" ] | ||||||
|  |                 |> List.tryFind (fun s -> s = i.idText) | ||||||
|  |                 |> Option.map ignore<string> | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|Byte|_|) (fieldType : SynType) : unit option = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent with | ||||||
|  |             | [ i ] -> [ "byte" ] |> List.tryFind (fun s -> s = i.idText) |> Option.map ignore<string> | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|Guid|_|) (fieldType : SynType) : unit option = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "System" ; "Guid" ] | ||||||
|  |             | [ "Guid" ] -> Some () | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|HttpResponseMessage|_|) (fieldType : SynType) : unit option = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "System" ; "Net" ; "Http" ; "HttpResponseMessage" ] | ||||||
|  |             | [ "Net" ; "Http" ; "HttpResponseMessage" ] | ||||||
|  |             | [ "Http" ; "HttpResponseMessage" ] | ||||||
|  |             | [ "HttpResponseMessage" ] -> Some () | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|HttpContent|_|) (fieldType : SynType) : unit option = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "System" ; "Net" ; "Http" ; "HttpContent" ] | ||||||
|  |             | [ "Net" ; "Http" ; "HttpContent" ] | ||||||
|  |             | [ "Http" ; "HttpContent" ] | ||||||
|  |             | [ "HttpContent" ] -> Some () | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|Stream|_|) (fieldType : SynType) : unit option = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "System" ; "IO" ; "Stream" ] | ||||||
|  |             | [ "IO" ; "Stream" ] | ||||||
|  |             | [ "Stream" ] -> Some () | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|NumberType|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent ident -> | ||||||
|  |             match ident.LongIdent with | ||||||
|  |             | [ i ] -> [ "string" ; "float" ; "int" ; "bool" ] |> List.tryFind (fun s -> s = i.idText) | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|DateOnly|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> | ||||||
|  |             match ident |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "System" ; "DateOnly" ] | ||||||
|  |             | [ "DateOnly" ] -> Some () | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|DateTime|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> | ||||||
|  |             match ident |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "System" ; "DateTime" ] | ||||||
|  |             | [ "DateTime" ] -> Some () | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|Uri|_|) (fieldType : SynType) = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> | ||||||
|  |             match ident |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "System" ; "Uri" ] | ||||||
|  |             | [ "Uri" ] -> Some () | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|  |  | ||||||
|  |     let (|Task|_|) (fieldType : SynType) : SynType option = | ||||||
|  |         match fieldType with | ||||||
|  |         | SynType.App (SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)), _, args, _, _, _, _) -> | ||||||
|  |             match ident |> List.map (fun i -> i.idText) with | ||||||
|  |             | [ "Task" ] | ||||||
|  |             | [ "Tasks" ; "Task" ] | ||||||
|  |             | [ "Threading" ; "Tasks" ; "Task" ] | ||||||
|  |             | [ "System" ; "Threading" ; "Tasks" ; "Task" ] -> | ||||||
|  |                 match args with | ||||||
|  |                 | [ arg ] -> Some arg | ||||||
|  |                 | _ -> failwithf "Expected Task to be applied to exactly one arg, but got: %+A" args | ||||||
|  |             | _ -> None | ||||||
|  |         | _ -> None | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -3,14 +3,12 @@ namespace WoofWare.Myriad.Plugins | |||||||
| open System | open System | ||||||
| open System.Text | open System.Text | ||||||
| open Fantomas.FCS.Syntax | open Fantomas.FCS.Syntax | ||||||
| open Fantomas.FCS.Text.Range | open Myriad.Core | ||||||
| 
 | 
 | ||||||
| [<RequireQualifiedAccess>] | [<RequireQualifiedAccess>] | ||||||
| module internal Ident = | module internal Ident = | ||||||
|     let inline create (s : string) = Ident (s, range0) |  | ||||||
| 
 |  | ||||||
|     let lowerFirstLetter (x : Ident) : Ident = |     let lowerFirstLetter (x : Ident) : Ident = | ||||||
|         let result = StringBuilder x.idText.Length |         let result = StringBuilder x.idText.Length | ||||||
|         result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore |         result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore | ||||||
|         result.Append x.idText.[1..] |> ignore |         result.Append x.idText.[1..] |> ignore | ||||||
|         create ((result : StringBuilder).ToString ()) |         Ident.Create ((result : StringBuilder).ToString ()) | ||||||
| @@ -2,7 +2,9 @@ namespace WoofWare.Myriad.Plugins | |||||||
|  |  | ||||||
| open System | open System | ||||||
| open Fantomas.FCS.Syntax | open Fantomas.FCS.Syntax | ||||||
|  | open Fantomas.FCS.SyntaxTrivia | ||||||
| open Fantomas.FCS.Xml | open Fantomas.FCS.Xml | ||||||
|  | open Myriad.Core | ||||||
|  |  | ||||||
| type internal GenerateMockOutputSpec = | type internal GenerateMockOutputSpec = | ||||||
|     { |     { | ||||||
| @@ -12,15 +14,13 @@ type internal GenerateMockOutputSpec = | |||||||
| [<RequireQualifiedAccess>] | [<RequireQualifiedAccess>] | ||||||
| module internal InterfaceMockGenerator = | module internal InterfaceMockGenerator = | ||||||
|     open Fantomas.FCS.Text.Range |     open Fantomas.FCS.Text.Range | ||||||
|  |     open Myriad.Core.Ast | ||||||
|  |  | ||||||
|     let private getName (SynField (_, _, id, _, _, _, _, _, _)) = |     let private getName (SynField (_, _, id, _, _, _, _, _, _)) = | ||||||
|         match id with |         match id with | ||||||
|         | None -> failwith "Expected record field to have a name, but it was somehow anonymous" |         | None -> failwith "Expected record field to have a name, but it was somehow anonymous" | ||||||
|         | Some id -> id |         | Some id -> id | ||||||
|  |  | ||||||
|     [<RequireQualifiedAccess>] |  | ||||||
|     type private KnownInheritance = | IDisposable |  | ||||||
|  |  | ||||||
|     let createType |     let createType | ||||||
|         (spec : GenerateMockOutputSpec) |         (spec : GenerateMockOutputSpec) | ||||||
|         (name : string) |         (name : string) | ||||||
| @@ -29,101 +29,157 @@ module internal InterfaceMockGenerator = | |||||||
|         (fields : SynField list) |         (fields : SynField list) | ||||||
|         : SynModuleDecl |         : SynModuleDecl | ||||||
|         = |         = | ||||||
|         let inherits = |         let synValData = | ||||||
|             interfaceType.Inherits |             { | ||||||
|             |> Seq.map (fun ty -> |                 SynMemberFlags.IsInstance = false | ||||||
|                 match ty with |                 SynMemberFlags.IsDispatchSlot = false | ||||||
|                 | SynType.LongIdent (SynLongIdent.SynLongIdent (name, _, _)) -> |                 SynMemberFlags.IsOverrideOrExplicitImpl = false | ||||||
|                     match name |> List.map _.idText with |                 SynMemberFlags.IsFinal = false | ||||||
|                     | [] -> failwith "Unexpected empty identifier in inheritance declaration" |                 SynMemberFlags.GetterOrSetterIsCompilerGenerated = false | ||||||
|                     | [ "IDisposable" ] |                 SynMemberFlags.MemberKind = SynMemberKind.Member | ||||||
|                     | [ "System" ; "IDisposable" ] -> KnownInheritance.IDisposable |             } | ||||||
|                     | _ -> failwithf "Unrecognised inheritance identifier: %+A" name |  | ||||||
|                 | x -> failwithf "Unrecognised type in inheritance: %+A" x |  | ||||||
|             ) |  | ||||||
|             |> Set.ofSeq |  | ||||||
|  |  | ||||||
|         let failwithFun = |         let failwithFun = | ||||||
|             SynExpr.createLongIdent [ "System" ; "NotImplementedException" ] |             SynExpr.createLambda | ||||||
|             |> SynExpr.applyTo (SynExpr.CreateConst "Unimplemented mock function") |                 "x" | ||||||
|             |> SynExpr.paren |                 (SynExpr.CreateApp ( | ||||||
|             |> SynExpr.applyFunction (SynExpr.createIdent "raise") |                     SynExpr.CreateIdentString "raise", | ||||||
|             |> SynExpr.createLambda "_" |                     SynExpr.CreateParen ( | ||||||
|  |                         SynExpr.CreateApp ( | ||||||
|  |                             SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "NotImplementedException" ]), | ||||||
|  |                             SynExpr.CreateConstString "Unimplemented mock function" | ||||||
|  |                         ) | ||||||
|  |                     ) | ||||||
|  |                 )) | ||||||
|  |  | ||||||
|  |         let constructorIdent = | ||||||
|  |             let generics = | ||||||
|  |                 interfaceType.Generics | ||||||
|  |                 |> Option.map (fun generics -> SynValTyparDecls (Some generics, false)) | ||||||
|  |  | ||||||
|  |             SynPat.LongIdent ( | ||||||
|  |                 SynLongIdent.CreateString "Empty", | ||||||
|  |                 None, | ||||||
|  |                 None, // no generics on the "Empty", only on the return type | ||||||
|  |                 SynArgPats.Pats ( | ||||||
|  |                     if generics.IsNone then | ||||||
|  |                         [] | ||||||
|  |                     else | ||||||
|  |                         [ SynPat.CreateParen (SynPat.CreateConst SynConst.Unit) ] | ||||||
|  |                 ), | ||||||
|  |                 None, | ||||||
|  |                 range0 | ||||||
|  |             ) | ||||||
|  |  | ||||||
|         let constructorReturnType = |         let constructorReturnType = | ||||||
|             match interfaceType.Generics with |             match interfaceType.Generics with | ||||||
|             | None -> SynType.createLongIdent' [ name ] |             | None -> SynType.CreateLongIdent name | ||||||
|             | Some generics -> |             | Some generics -> | ||||||
|  |  | ||||||
|                 let generics = |                 let generics = | ||||||
|                     generics.TyparDecls |                     generics.TyparDecls | ||||||
|                 |> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar) |                     |> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0)) | ||||||
|  |  | ||||||
|             SynType.app name generics |                 SynType.App ( | ||||||
|  |                     SynType.CreateLongIdent name, | ||||||
|         let constructorFields = |                     Some range0, | ||||||
|             let extras = |                     generics, | ||||||
|                 if inherits.Contains KnownInheritance.IDisposable then |                     List.replicate (generics.Length - 1) range0, | ||||||
|                     let unitFun = SynExpr.createThunk (SynExpr.CreateConst ()) |                     Some range0, | ||||||
|  |                     false, | ||||||
|                     [ (SynLongIdent.createS "Dispose", true), Some unitFun ] |                     range0 | ||||||
|                 else |                 ) | ||||||
|                     [] |             |> SynBindingReturnInfo.Create | ||||||
|  |  | ||||||
|             let nonExtras = |  | ||||||
|                 fields |  | ||||||
|                 |> List.map (fun field -> (SynLongIdent.createI (getName field), true), Some failwithFun) |  | ||||||
|  |  | ||||||
|             extras @ nonExtras |  | ||||||
|  |  | ||||||
|         let constructor = |         let constructor = | ||||||
|             SynBinding.basic |             SynMemberDefn.Member ( | ||||||
|                 [ Ident.create "Empty" ] |                 SynBinding.SynBinding ( | ||||||
|                 (if interfaceType.Generics.IsNone then |                     None, | ||||||
|                      [] |                     SynBindingKind.Normal, | ||||||
|                  else |                     false, | ||||||
|                      [ SynPat.unit ]) |                     false, | ||||||
|                 (AstHelper.instantiateRecord constructorFields) |                     [], | ||||||
|             |> SynBinding.withXmlDoc (PreXmlDoc.create "An implementation where every method throws.") |                     PreXmlDoc.Create " An implementation where every method throws.", | ||||||
|             |> SynBinding.withReturnAnnotation constructorReturnType |                     SynValData.SynValData (Some synValData, SynValInfo.Empty, None), | ||||||
|             |> SynMemberDefn.staticMember |                     constructorIdent, | ||||||
|  |                     Some constructorReturnType, | ||||||
|         let fields = |                     AstHelper.instantiateRecord ( | ||||||
|             let extras = |                         fields | ||||||
|                 if inherits.Contains KnownInheritance.IDisposable then |                         |> List.map (fun field -> | ||||||
|                     { |                             ((SynLongIdent.CreateFromLongIdent [ getName field ], true), Some failwithFun) | ||||||
|                         Attrs = [] |                         ) | ||||||
|                         Ident = Some (Ident.create "Dispose") |                     ), | ||||||
|                         Type = SynType.funFromDomain SynType.unit SynType.unit |                     range0, | ||||||
|  |                     DebugPointAtBinding.Yes range0, | ||||||
|  |                     { SynExpr.synBindingTriviaZero true with | ||||||
|  |                         LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0) | ||||||
|                     } |                     } | ||||||
|                     |> SynField.make |                 ), | ||||||
|                     |> SynField.withDocString (PreXmlDoc.create "Implementation of IDisposable.Dispose") |                 range0 | ||||||
|                     |> List.singleton |             ) | ||||||
|                 else |  | ||||||
|                     [] |  | ||||||
|  |  | ||||||
|             extras @ fields |  | ||||||
|  |  | ||||||
|         let interfaceMembers = |         let interfaceMembers = | ||||||
|             let members = |             let members = | ||||||
|                 interfaceType.Members |                 interfaceType.Members | ||||||
|                 |> List.map (fun memberInfo -> |                 |> List.map (fun memberInfo -> | ||||||
|  |  | ||||||
|  |                     let synValData = | ||||||
|  |                         SynValData.SynValData ( | ||||||
|  |                             Some | ||||||
|  |                                 { | ||||||
|  |                                     IsInstance = true | ||||||
|  |                                     IsDispatchSlot = false | ||||||
|  |                                     IsOverrideOrExplicitImpl = true | ||||||
|  |                                     IsFinal = false | ||||||
|  |                                     GetterOrSetterIsCompilerGenerated = false | ||||||
|  |                                     MemberKind = SynMemberKind.Member | ||||||
|  |                                 }, | ||||||
|  |                             valInfo = | ||||||
|  |                                 SynValInfo.SynValInfo ( | ||||||
|  |                                     curriedArgInfos = | ||||||
|  |                                         [ | ||||||
|  |                                             yield | ||||||
|  |                                                 [ | ||||||
|  |                                                     SynArgInfo.SynArgInfo ( | ||||||
|  |                                                         attributes = [], | ||||||
|  |                                                         optional = false, | ||||||
|  |                                                         ident = None | ||||||
|  |                                                     ) | ||||||
|  |                                                 ] | ||||||
|  |                                             yield! | ||||||
|  |                                                 memberInfo.Args | ||||||
|  |                                                 |> List.mapi (fun i arg -> | ||||||
|  |                                                     arg.Args | ||||||
|  |                                                     |> List.mapi (fun j arg -> | ||||||
|  |                                                         SynArgInfo.CreateIdString $"arg_%i{i}_%i{j}" | ||||||
|  |                                                     ) | ||||||
|  |                                                 ) | ||||||
|  |                                         ], | ||||||
|  |                                     returnInfo = | ||||||
|  |                                         SynArgInfo.SynArgInfo (attributes = [], optional = false, ident = None) | ||||||
|  |                                 ), | ||||||
|  |                             thisIdOpt = None | ||||||
|  |                         ) | ||||||
|  |  | ||||||
|                     let headArgs = |                     let headArgs = | ||||||
|                         memberInfo.Args |                         memberInfo.Args | ||||||
|                         |> List.mapi (fun i tupledArgs -> |                         |> List.mapi (fun i tupledArgs -> | ||||||
|                             let args = |                             let args = | ||||||
|                                 tupledArgs.Args |                                 tupledArgs.Args | ||||||
|                                 |> List.mapi (fun j ty -> |                                 |> List.mapi (fun j _ -> SynPat.CreateNamed (Ident.Create $"arg_%i{i}_%i{j}")) | ||||||
|                                     match ty.Type with |  | ||||||
|                                     | UnitType -> SynPat.unit |                             SynPat.Tuple (false, args, List.replicate (args.Length - 1) range0, range0) | ||||||
|                                     | _ -> SynPat.named $"arg_%i{i}_%i{j}" |                             |> SynPat.CreateParen | ||||||
|  |                             |> fun i -> if tupledArgs.HasParen then SynPat.Paren (i, range0) else i | ||||||
|                         ) |                         ) | ||||||
|  |  | ||||||
|                             match args with |                     let headPat = | ||||||
|                             | [] -> failwith "somehow got no args at all" |                         SynPat.LongIdent ( | ||||||
|                             | [ arg ] -> arg |                             SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; memberInfo.Identifier ], | ||||||
|                             | args -> SynPat.tuple args |                             None, | ||||||
|                             |> fun i -> if tupledArgs.HasParen then SynPat.paren i else i |                             None, | ||||||
|  |                             SynArgPats.Pats headArgs, | ||||||
|  |                             None, | ||||||
|  |                             range0 | ||||||
|                         ) |                         ) | ||||||
|  |  | ||||||
|                     let body = |                     let body = | ||||||
| @@ -131,12 +187,8 @@ module internal InterfaceMockGenerator = | |||||||
|                             memberInfo.Args |                             memberInfo.Args | ||||||
|                             |> List.mapi (fun i args -> |                             |> List.mapi (fun i args -> | ||||||
|                                 args.Args |                                 args.Args | ||||||
|                                 |> List.mapi (fun j arg -> |                                 |> List.mapi (fun j args -> SynExpr.CreateIdentString $"arg_%i{i}_%i{j}") | ||||||
|                                     match arg.Type with |                                 |> SynExpr.CreateParenedTuple | ||||||
|                                     | UnitType -> SynExpr.CreateConst () |  | ||||||
|                                     | _ -> SynExpr.createIdent $"arg_%i{i}_%i{j}" |  | ||||||
|                                 ) |  | ||||||
|                                 |> SynExpr.tuple |  | ||||||
|                             ) |                             ) | ||||||
|  |  | ||||||
|                         match tuples |> List.rev with |                         match tuples |> List.rev with | ||||||
| @@ -144,17 +196,42 @@ module internal InterfaceMockGenerator = | |||||||
|                         | last :: rest -> |                         | last :: rest -> | ||||||
|  |  | ||||||
|                         (last, rest) |                         (last, rest) | ||||||
|                         ||> List.fold SynExpr.applyTo |                         ||> List.fold (fun trail next -> SynExpr.CreateApp (next, trail)) | ||||||
|                         |> SynExpr.applyFunction ( |                         |> fun args -> | ||||||
|                             SynExpr.createLongIdent' [ Ident.create "this" ; memberInfo.Identifier ] |                             SynExpr.CreateApp ( | ||||||
|  |                                 SynExpr.CreateLongIdent ( | ||||||
|  |                                     SynLongIdent.CreateFromLongIdent [ Ident.Create "this" ; memberInfo.Identifier ] | ||||||
|  |                                 ), | ||||||
|  |                                 args | ||||||
|                             ) |                             ) | ||||||
|  |  | ||||||
|                     SynBinding.basic [ Ident.create "this" ; memberInfo.Identifier ] headArgs body |                     SynMemberDefn.Member ( | ||||||
|                     |> SynMemberDefn.memberImplementation |                         SynBinding.SynBinding ( | ||||||
|  |                             None, | ||||||
|  |                             SynBindingKind.Normal, | ||||||
|  |                             false, | ||||||
|  |                             false, | ||||||
|  |                             [], | ||||||
|  |                             PreXmlDoc.Empty, | ||||||
|  |                             synValData, | ||||||
|  |                             headPat, | ||||||
|  |                             None, | ||||||
|  |                             body, | ||||||
|  |                             range0, | ||||||
|  |                             DebugPointAtBinding.Yes range0, | ||||||
|  |                             { | ||||||
|  |                                 LeadingKeyword = SynLeadingKeyword.Member range0 | ||||||
|  |                                 InlineKeyword = None | ||||||
|  |                                 EqualsRange = Some range0 | ||||||
|  |                             } | ||||||
|  |                         ), | ||||||
|  |                         range0 | ||||||
|  |                     ) | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|             let interfaceName = |             let interfaceName = | ||||||
|                 let baseName = SynType.createLongIdent interfaceType.Name |                 let baseName = | ||||||
|  |                     SynType.CreateLongIdent (SynLongIdent.CreateFromLongIdent interfaceType.Name) | ||||||
|  |  | ||||||
|                 match interfaceType.Generics with |                 match interfaceType.Generics with | ||||||
|                 | None -> baseName |                 | None -> baseName | ||||||
| @@ -164,9 +241,17 @@ module internal InterfaceMockGenerator = | |||||||
|                         | SynTyparDecls.PostfixList (decls, _, _) -> decls |                         | SynTyparDecls.PostfixList (decls, _, _) -> decls | ||||||
|                         | SynTyparDecls.PrefixList (decls, _) -> decls |                         | SynTyparDecls.PrefixList (decls, _) -> decls | ||||||
|                         | SynTyparDecls.SinglePrefix (decl, _) -> [ decl ] |                         | SynTyparDecls.SinglePrefix (decl, _) -> [ decl ] | ||||||
|                         |> List.map (fun (SynTyparDecl (_, typar)) -> SynType.var typar) |                         |> List.map (fun (SynTyparDecl (_, typar)) -> SynType.Var (typar, range0)) | ||||||
|  |  | ||||||
|                     SynType.app' baseName generics |                     SynType.App ( | ||||||
|  |                         baseName, | ||||||
|  |                         Some range0, | ||||||
|  |                         generics, | ||||||
|  |                         List.replicate (generics.Length - 1) range0, | ||||||
|  |                         Some range0, | ||||||
|  |                         false, | ||||||
|  |                         range0 | ||||||
|  |                     ) | ||||||
|  |  | ||||||
|             SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0) |             SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0) | ||||||
|  |  | ||||||
| @@ -179,32 +264,11 @@ module internal InterfaceMockGenerator = | |||||||
|             | Some (SynAccess.Internal _), _ -> SynAccess.Internal range0 |             | Some (SynAccess.Internal _), _ -> SynAccess.Internal range0 | ||||||
|             | Some (SynAccess.Private _), _ -> SynAccess.Private range0 |             | Some (SynAccess.Private _), _ -> SynAccess.Private range0 | ||||||
|  |  | ||||||
|         let extraInterfaces = |  | ||||||
|             inherits |  | ||||||
|             |> Seq.map (fun inheritance -> |  | ||||||
|                 match inheritance with |  | ||||||
|                 | KnownInheritance.IDisposable -> |  | ||||||
|                     let mem = |  | ||||||
|                         SynExpr.createLongIdent [ "this" ; "Dispose" ] |  | ||||||
|                         |> SynExpr.applyTo (SynExpr.CreateConst ()) |  | ||||||
|                         |> SynBinding.basic [ Ident.create "this" ; Ident.create "Dispose" ] [ SynPat.unit ] |  | ||||||
|                         |> SynBinding.withReturnAnnotation SynType.unit |  | ||||||
|                         |> SynMemberDefn.memberImplementation |  | ||||||
|  |  | ||||||
|                     SynMemberDefn.Interface ( |  | ||||||
|                         SynType.createLongIdent' [ "System" ; "IDisposable" ], |  | ||||||
|                         Some range0, |  | ||||||
|                         Some [ mem ], |  | ||||||
|                         range0 |  | ||||||
|                     ) |  | ||||||
|             ) |  | ||||||
|             |> Seq.toList |  | ||||||
|  |  | ||||||
|         let record = |         let record = | ||||||
|             { |             { | ||||||
|                 Name = Ident.create name |                 Name = Ident.Create name | ||||||
|                 Fields = fields |                 Fields = fields | ||||||
|                 Members = Some ([ constructor ; interfaceMembers ] @ extraInterfaces) |                 Members = Some [ constructor ; interfaceMembers ] | ||||||
|                 XmlDoc = Some xmlDoc |                 XmlDoc = Some xmlDoc | ||||||
|                 Generics = interfaceType.Generics |                 Generics = interfaceType.Generics | ||||||
|                 Accessibility = Some access |                 Accessibility = Some access | ||||||
| @@ -216,7 +280,7 @@ module internal InterfaceMockGenerator = | |||||||
|  |  | ||||||
|     let private buildType (x : ParameterInfo) : SynType = |     let private buildType (x : ParameterInfo) : SynType = | ||||||
|         if x.IsOptional then |         if x.IsOptional then | ||||||
|             SynType.app "option" [ x.Type ] |             SynType.App (SynType.CreateLongIdent "option", Some range0, [ x.Type ], [], Some range0, false, range0) | ||||||
|         else |         else | ||||||
|             x.Type |             x.Type | ||||||
|  |  | ||||||
| @@ -233,15 +297,19 @@ module internal InterfaceMockGenerator = | |||||||
|     let constructMember (mem : MemberInfo) : SynField = |     let constructMember (mem : MemberInfo) : SynField = | ||||||
|         let inputType = mem.Args |> List.map constructMemberSinglePlace |         let inputType = mem.Args |> List.map constructMemberSinglePlace | ||||||
|  |  | ||||||
|         let funcType = SynType.toFun inputType mem.ReturnType |         let funcType = AstHelper.toFun inputType mem.ReturnType | ||||||
|  |  | ||||||
|         { |         SynField.SynField ( | ||||||
|             Type = funcType |             [], | ||||||
|             Attrs = [] |             false, | ||||||
|             Ident = Some mem.Identifier |             Some mem.Identifier, | ||||||
|         } |             funcType, | ||||||
|         |> SynField.make |             false, | ||||||
|         |> SynField.withDocString (mem.XmlDoc |> Option.defaultValue PreXmlDoc.Empty) |             mem.XmlDoc |> Option.defaultValue PreXmlDoc.Empty, | ||||||
|  |             None, | ||||||
|  |             range0, | ||||||
|  |             SynFieldTrivia.Zero | ||||||
|  |         ) | ||||||
|  |  | ||||||
|     let createRecord |     let createRecord | ||||||
|         (namespaceId : LongIdent) |         (namespaceId : LongIdent) | ||||||
| @@ -251,24 +319,25 @@ module internal InterfaceMockGenerator = | |||||||
|         = |         = | ||||||
|         let interfaceType = AstHelper.parseInterface interfaceType |         let interfaceType = AstHelper.parseInterface interfaceType | ||||||
|         let fields = interfaceType.Members |> List.map constructMember |         let fields = interfaceType.Members |> List.map constructMember | ||||||
|         let docString = PreXmlDoc.create "Mock record type for an interface" |         let docString = PreXmlDoc.Create " Mock record type for an interface" | ||||||
|  |  | ||||||
|         let name = |         let name = | ||||||
|             List.last interfaceType.Name |             List.last interfaceType.Name | ||||||
|             |> _.idText |             |> _.idText | ||||||
|             |> fun s -> |             |> fun s -> | ||||||
|                 if s.StartsWith 'I' && s.Length > 1 && Char.IsUpper s.[1] then |                 if s.StartsWith 'I' && s.Length > 1 && Char.IsUpper s.[1] then | ||||||
|                     s.Substring 1 |                     s.[1..] | ||||||
|                 else |                 else | ||||||
|                     s |                     s | ||||||
|             |> fun s -> s + "Mock" |             |> fun s -> s + "Mock" | ||||||
|  |  | ||||||
|         let typeDecl = createType spec name interfaceType docString fields |         let typeDecl = createType spec name interfaceType docString fields | ||||||
|  |  | ||||||
|         [ yield! opens |> List.map SynModuleDecl.openAny ; yield typeDecl ] |  | ||||||
|         |> SynModuleOrNamespace.createNamespace namespaceId |  | ||||||
|  |  | ||||||
| open Myriad.Core |         SynModuleOrNamespace.CreateNamespace ( | ||||||
|  |             namespaceId, | ||||||
|  |             decls = (opens |> List.map SynModuleDecl.CreateOpen) @ [ typeDecl ] | ||||||
|  |         ) | ||||||
|  |  | ||||||
| /// Myriad generator that creates a record which implements the given interface, | /// Myriad generator that creates a record which implements the given interface, | ||||||
| /// but with every field mocked out. | /// but with every field mocked out. | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ open System | |||||||
| open System.Text | open System.Text | ||||||
| open Fantomas.FCS.Syntax | open Fantomas.FCS.Syntax | ||||||
| open Fantomas.FCS.SyntaxTrivia | open Fantomas.FCS.SyntaxTrivia | ||||||
|  | open Fantomas.FCS.Xml | ||||||
|  | open Myriad.Core | ||||||
|  |  | ||||||
| type internal JsonParseOutputSpec = | type internal JsonParseOutputSpec = | ||||||
|     { |     { | ||||||
| @@ -13,6 +15,7 @@ type internal JsonParseOutputSpec = | |||||||
| [<RequireQualifiedAccess>] | [<RequireQualifiedAccess>] | ||||||
| module internal JsonParseGenerator = | module internal JsonParseGenerator = | ||||||
|     open Fantomas.FCS.Text.Range |     open Fantomas.FCS.Text.Range | ||||||
|  |     open Myriad.Core.Ast | ||||||
|  |  | ||||||
|     type JsonParseOption = |     type JsonParseOption = | ||||||
|         { |         { | ||||||
| @@ -27,34 +30,38 @@ module internal JsonParseGenerator = | |||||||
|     /// (match {indexed} with | null -> raise (System.Collections.Generic.KeyNotFoundException ()) | v -> v) |     /// (match {indexed} with | null -> raise (System.Collections.Generic.KeyNotFoundException ()) | v -> v) | ||||||
|     let assertNotNull (propertyName : SynExpr) (indexed : SynExpr) = |     let assertNotNull (propertyName : SynExpr) (indexed : SynExpr) = | ||||||
|         let raiseExpr = |         let raiseExpr = | ||||||
|             SynExpr.applyFunction |             SynExpr.CreateApp ( | ||||||
|                 (SynExpr.createIdent "sprintf") |                 SynExpr.CreateIdentString "raise", | ||||||
|                 (SynExpr.CreateConst "Required key '%s' not found on JSON object") |                 SynExpr.CreateParen ( | ||||||
|             |> SynExpr.applyTo (SynExpr.paren propertyName) |                     SynExpr.CreateApp ( | ||||||
|             |> SynExpr.paren |                         SynExpr.CreateLongIdent ( | ||||||
|             |> SynExpr.applyFunction ( |                             SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ] | ||||||
|                 SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyNotFoundException" ] |                         ), | ||||||
|  |                         SynExpr.CreateParen ( | ||||||
|  |                             SynExpr.CreateApp ( | ||||||
|  |                                 SynExpr.CreateApp ( | ||||||
|  |                                     SynExpr.CreateIdentString "sprintf", | ||||||
|  |                                     SynExpr.CreateConstString "Required key '%s' not found on JSON object" | ||||||
|  |                                 ), | ||||||
|  |                                 SynExpr.CreateParen propertyName | ||||||
|  |                             ) | ||||||
|  |                         ) | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|             ) |             ) | ||||||
|             |> SynExpr.paren |  | ||||||
|             |> SynExpr.applyFunction (SynExpr.createIdent "raise") |  | ||||||
|  |  | ||||||
|  |         SynExpr.CreateMatch ( | ||||||
|  |             indexed, | ||||||
|             [ |             [ | ||||||
|             SynMatchClause.create SynPat.createNull raiseExpr |                 SynMatchClause.Create (SynPat.CreateNull, None, raiseExpr) | ||||||
|             SynMatchClause.create (SynPat.named "v") (SynExpr.createIdent "v") |                 SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, SynExpr.CreateIdentString "v") | ||||||
|             ] |             ] | ||||||
|         |> SynExpr.createMatch indexed |         ) | ||||||
|         |> SynExpr.paren |         |> SynExpr.CreateParen | ||||||
|  |  | ||||||
|     /// {node}.AsValue().GetValue<{typeName}> () |     /// {node}.AsValue().GetValue<{typeName}> () | ||||||
|     /// If `propertyName` is Some, uses `assertNotNull {node}` instead of `{node}`. |     /// If `propertyName` is Some, uses `assertNotNull {node}` instead of `{node}`. | ||||||
|     let asValueGetValue (propertyName : SynExpr option) (typeName : string) (node : SynExpr) : SynExpr = |     let asValueGetValue (propertyName : SynExpr option) (typeName : string) (node : SynExpr) : SynExpr = | ||||||
|         match propertyName with |  | ||||||
|         | None -> node |  | ||||||
|         | Some propertyName -> assertNotNull propertyName node |  | ||||||
|         |> SynExpr.callMethod "AsValue" |  | ||||||
|         |> SynExpr.callGenericMethod' "GetValue" typeName |  | ||||||
|  |  | ||||||
|     let asValueGetValueIdent (propertyName : SynExpr option) (typeName : LongIdent) (node : SynExpr) : SynExpr = |  | ||||||
|         match propertyName with |         match propertyName with | ||||||
|         | None -> node |         | None -> node | ||||||
|         | Some propertyName -> assertNotNull propertyName node |         | Some propertyName -> assertNotNull propertyName node | ||||||
| @@ -71,8 +78,10 @@ module internal JsonParseGenerator = | |||||||
|  |  | ||||||
|     /// {type}.jsonParse {node} |     /// {type}.jsonParse {node} | ||||||
|     let typeJsonParse (typeName : LongIdent) (node : SynExpr) : SynExpr = |     let typeJsonParse (typeName : LongIdent) (node : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (typeName @ [ Ident.Create "jsonParse" ])), | ||||||
|             node |             node | ||||||
|         |> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ Ident.create "jsonParse" ])) |         ) | ||||||
|  |  | ||||||
|     /// collectionType is e.g. "List"; we'll be calling `ofSeq` on it. |     /// collectionType is e.g. "List"; we'll be calling `ofSeq` on it. | ||||||
|     /// body is the body of a lambda which takes a parameter `elt`. |     /// body is the body of a lambda which takes a parameter `elt`. | ||||||
| @@ -91,41 +100,64 @@ module internal JsonParseGenerator = | |||||||
|         | Some propertyName -> assertNotNull propertyName node |         | Some propertyName -> assertNotNull propertyName node | ||||||
|         |> SynExpr.callMethod "AsArray" |         |> SynExpr.callMethod "AsArray" | ||||||
|         |> SynExpr.pipeThroughFunction ( |         |> SynExpr.pipeThroughFunction ( | ||||||
|             SynExpr.applyFunction (SynExpr.createLongIdent [ "Seq" ; "map" ]) (SynExpr.createLambda "elt" body) |             SynExpr.CreateApp ( | ||||||
|  |                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]), | ||||||
|  |                 SynExpr.createLambda "elt" body | ||||||
|             ) |             ) | ||||||
|         |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ collectionType ; "ofSeq" ]) |         ) | ||||||
|  |         |> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ collectionType ; "ofSeq" ])) | ||||||
|  |  | ||||||
|     /// match {node} with | null -> None | v -> {body} |> Some |     /// match {node} with | null -> None | v -> {body} |> Some | ||||||
|     /// Use the variable `v` to get access to the `Some`. |     /// Use the variable `v` to get access to the `Some`. | ||||||
|     let createParseLineOption (node : SynExpr) (body : SynExpr) : SynExpr = |     let createParseLineOption (node : SynExpr) (body : SynExpr) : SynExpr = | ||||||
|         let body = SynExpr.pipeThroughFunction (SynExpr.createIdent "Some") body |         let body = SynExpr.pipeThroughFunction (SynExpr.CreateIdentString "Some") body | ||||||
|  |  | ||||||
|  |         SynExpr.CreateMatch ( | ||||||
|  |             node, | ||||||
|             [ |             [ | ||||||
|             SynMatchClause.create SynPat.createNull (SynExpr.createIdent "None") |                 SynMatchClause.Create (SynPat.CreateNull, None, SynExpr.CreateIdent (Ident.Create "None")) | ||||||
|             SynMatchClause.create (SynPat.named "v") body |                 SynMatchClause.Create (SynPat.CreateNamed (Ident.Create "v"), None, body) | ||||||
|             ] |             ] | ||||||
|         |> SynExpr.createMatch node |         ) | ||||||
|  |  | ||||||
|     /// Given e.g. "float", returns "System.Double.Parse" |     /// Given e.g. "float", returns "System.Double.Parse" | ||||||
|     let parseFunction (typeName : string) : LongIdent = |     let parseFunction (typeName : string) : LongIdent = | ||||||
|         let qualified = |         List.append (SynExpr.qualifyPrimitiveType typeName) [ Ident.Create "Parse" ] | ||||||
|             match Primitives.qualifyType typeName with |  | ||||||
|             | Some x -> x |  | ||||||
|             | None -> failwith $"Could not recognise type %s{typeName} as a primitive." |  | ||||||
|  |  | ||||||
|         List.append qualified [ Ident.create "Parse" ] |  | ||||||
|  |  | ||||||
|     /// fun kvp -> let key = {key(kvp)} in let value = {value(kvp)} in (key, value)) |     /// fun kvp -> let key = {key(kvp)} in let value = {value(kvp)} in (key, value)) | ||||||
|     /// The inputs will be fed with appropriate SynExprs to apply them to the `kvp.Key` and `kvp.Value` args. |     /// The inputs will be fed with appropriate SynExprs to apply them to the `kvp.Key` and `kvp.Value` args. | ||||||
|     let dictionaryMapper (key : SynExpr -> SynExpr) (value : SynExpr -> SynExpr) : SynExpr = |     let dictionaryMapper (key : SynExpr -> SynExpr) (value : SynExpr -> SynExpr) : SynExpr = | ||||||
|         let keyArg = SynExpr.createLongIdent [ "kvp" ; "Key" ] |> SynExpr.paren |         let keyArg = | ||||||
|  |             SynExpr.CreateLongIdent (SynLongIdent.Create [ "kvp" ; "Key" ]) | ||||||
|  |             |> SynExpr.CreateParen | ||||||
|  |  | ||||||
|         let valueArg = SynExpr.createLongIdent [ "kvp" ; "Value" ] |> SynExpr.paren |         let valueArg = | ||||||
|  |             SynExpr.CreateLongIdent (SynLongIdent.Create [ "kvp" ; "Value" ]) | ||||||
|  |             |> SynExpr.CreateParen | ||||||
|  |  | ||||||
|         // No need to paren here, we're on the LHS of a `let` |         SynExpr.LetOrUse ( | ||||||
|         SynExpr.tupleNoParen [ SynExpr.createIdent "key" ; SynExpr.createIdent "value" ] |             false, | ||||||
|         |> SynExpr.createLet [ SynBinding.basic [ Ident.create "value" ] [] (value valueArg) ] |             false, | ||||||
|         |> SynExpr.createLet [ SynBinding.basic [ Ident.create "key" ] [] (key keyArg) ] |             [ | ||||||
|  |                 SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create "key"), expr = key keyArg) | ||||||
|  |             ], | ||||||
|  |             SynExpr.LetOrUse ( | ||||||
|  |                 false, | ||||||
|  |                 false, | ||||||
|  |                 [ | ||||||
|  |                     SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create "value"), expr = value valueArg) | ||||||
|  |                 ], | ||||||
|  |                 SynExpr.CreateTuple [ SynExpr.CreateIdentString "key" ; SynExpr.CreateIdentString "value" ], | ||||||
|  |                 range0, | ||||||
|  |                 { | ||||||
|  |                     InKeyword = None | ||||||
|  |                 } | ||||||
|  |             ), | ||||||
|  |             range0, | ||||||
|  |             { | ||||||
|  |                 InKeyword = None | ||||||
|  |             } | ||||||
|  |         ) | ||||||
|         |> SynExpr.createLambda "kvp" |         |> SynExpr.createLambda "kvp" | ||||||
|  |  | ||||||
|     /// A conforming JSON object has only strings as keys. But it would be reasonable to allow the user |     /// A conforming JSON object has only strings as keys. But it would be reasonable to allow the user | ||||||
| @@ -135,7 +167,7 @@ module internal JsonParseGenerator = | |||||||
|         | String -> key |         | String -> key | ||||||
|         | Uri -> |         | Uri -> | ||||||
|             key |             key | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Uri" ]) |             |> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ])) | ||||||
|         | _ -> |         | _ -> | ||||||
|             failwithf |             failwithf | ||||||
|                 $"Unable to parse the key type %+A{desiredType} of a JSON object. Keys are strings, and this plugin does not know how to convert to that from a string." |                 $"Unable to parse the key type %+A{desiredType} of a JSON object. Keys are strings, and this plugin does not know how to convert to that from a string." | ||||||
| @@ -155,19 +187,25 @@ module internal JsonParseGenerator = | |||||||
|         | DateOnly -> |         | DateOnly -> | ||||||
|             node |             node | ||||||
|             |> asValueGetValue propertyName "string" |             |> asValueGetValue propertyName "string" | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "DateOnly" ; "Parse" ]) |             |> SynExpr.pipeThroughFunction ( | ||||||
|  |                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "DateOnly" ; "Parse" ]) | ||||||
|  |             ) | ||||||
|         | Uri -> |         | Uri -> | ||||||
|             node |             node | ||||||
|             |> asValueGetValue propertyName "string" |             |> asValueGetValue propertyName "string" | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Uri" ]) |             |> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ])) | ||||||
|         | Guid -> |         | Guid -> | ||||||
|             node |             node | ||||||
|             |> asValueGetValue propertyName "string" |             |> asValueGetValue propertyName "string" | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "Guid" ; "Parse" ]) |             |> SynExpr.pipeThroughFunction ( | ||||||
|  |                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Guid" ; "Parse" ]) | ||||||
|  |             ) | ||||||
|         | DateTime -> |         | DateTime -> | ||||||
|             node |             node | ||||||
|             |> asValueGetValue propertyName "string" |             |> asValueGetValue propertyName "string" | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "System" ; "DateTime" ; "Parse" ]) |             |> SynExpr.pipeThroughFunction ( | ||||||
|  |                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "DateTime" ; "Parse" ]) | ||||||
|  |             ) | ||||||
|         | NumberType typeName -> |         | NumberType typeName -> | ||||||
|             let basic = asValueGetValue propertyName typeName node |             let basic = asValueGetValue propertyName typeName node | ||||||
|  |  | ||||||
| @@ -175,16 +213,26 @@ module internal JsonParseGenerator = | |||||||
|             | None -> basic |             | None -> basic | ||||||
|             | Some option -> |             | Some option -> | ||||||
|                 let cond = |                 let cond = | ||||||
|                     SynExpr.DotGet (SynExpr.createIdent "exc", range0, SynLongIdent.createS "Message", range0) |                     SynExpr.DotGet ( | ||||||
|                     |> SynExpr.callMethodArg "Contains" (SynExpr.CreateConst "cannot be converted to") |                         SynExpr.CreateIdentString "exc", | ||||||
|  |                         range0, | ||||||
|  |                         SynLongIdent.CreateString "Message", | ||||||
|  |                         range0 | ||||||
|  |                     ) | ||||||
|  |                     |> SynExpr.callMethodArg | ||||||
|  |                         "Contains" | ||||||
|  |                         (SynExpr.CreateConst (SynConst.CreateString "cannot be converted to")) | ||||||
|  |  | ||||||
|                 let handler = |                 let handler = | ||||||
|                     asValueGetValue propertyName "string" node |                     asValueGetValue propertyName "string" node | ||||||
|                     |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent' (parseFunction typeName)) |                     |> SynExpr.pipeThroughFunction ( | ||||||
|  |                         SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (parseFunction typeName)) | ||||||
|  |                     ) | ||||||
|                     |> SynExpr.ifThenElse |                     |> SynExpr.ifThenElse | ||||||
|                         (SynExpr.equals |                         (SynExpr.equals | ||||||
|                             option |                             option | ||||||
|                             (SynExpr.createLongIdent |                             (SynExpr.CreateLongIdent ( | ||||||
|  |                                 SynLongIdent.Create | ||||||
|                                     [ |                                     [ | ||||||
|                                         "System" |                                         "System" | ||||||
|                                         "Text" |                                         "Text" | ||||||
| @@ -192,75 +240,78 @@ module internal JsonParseGenerator = | |||||||
|                                         "Serialization" |                                         "Serialization" | ||||||
|                                         "JsonNumberHandling" |                                         "JsonNumberHandling" | ||||||
|                                         "AllowReadingFromString" |                                         "AllowReadingFromString" | ||||||
|                                 ])) |                                     ] | ||||||
|  |                             ))) | ||||||
|                         SynExpr.reraise |                         SynExpr.reraise | ||||||
|                     |> SynExpr.ifThenElse cond SynExpr.reraise |                     |> SynExpr.ifThenElse cond SynExpr.reraise | ||||||
|  |  | ||||||
|                 basic |                 basic | ||||||
|                 |> SynExpr.pipeThroughTryWith |                 |> SynExpr.pipeThroughTryWith | ||||||
|                     (SynPat.IsInst ( |                     (SynPat.IsInst ( | ||||||
|                         SynType.LongIdent (SynLongIdent.createS' [ "System" ; "InvalidOperationException" ]), |                         SynType.LongIdent (SynLongIdent.Create [ "System" ; "InvalidOperationException" ]), | ||||||
|                         range0 |                         range0 | ||||||
|                     )) |                     )) | ||||||
|                     handler |                     handler | ||||||
|         | PrimitiveType typeName -> asValueGetValueIdent propertyName typeName node |         | PrimitiveType typeName -> asValueGetValue propertyName typeName node | ||||||
|         | OptionType ty -> |         | OptionType ty -> | ||||||
|             parseNode None options ty (SynExpr.createIdent "v") |             parseNode None options ty (SynExpr.CreateIdentString "v") | ||||||
|             |> createParseLineOption node |             |> createParseLineOption node | ||||||
|         | ListType ty -> |         | ListType ty -> | ||||||
|             parseNode None options ty (SynExpr.createIdent "elt") |             parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt")) | ||||||
|             |> asArrayMapped propertyName "List" node |             |> asArrayMapped propertyName "List" node | ||||||
|         | ArrayType ty -> |         | ArrayType ty -> | ||||||
|             parseNode None options ty (SynExpr.createIdent "elt") |             parseNode None options ty (SynExpr.CreateLongIdent (SynLongIdent.CreateString "elt")) | ||||||
|             |> asArrayMapped propertyName "Array" node |             |> asArrayMapped propertyName "Array" node | ||||||
|         | IDictionaryType (keyType, valueType) -> |         | IDictionaryType (keyType, valueType) -> | ||||||
|             node |             node | ||||||
|             |> asObject propertyName |             |> asObject propertyName | ||||||
|             |> SynExpr.pipeThroughFunction ( |             |> SynExpr.pipeThroughFunction ( | ||||||
|                 SynExpr.applyFunction |                 SynExpr.CreateApp ( | ||||||
|                     (SynExpr.createLongIdent [ "Seq" ; "map" ]) |                     SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]), | ||||||
|                     (dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)) |                     dictionaryMapper (parseKeyString keyType) (parseNode None options valueType) | ||||||
|                 ) |                 ) | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createIdent "dict") |             ) | ||||||
|  |             |> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "dict" ])) | ||||||
|         | DictionaryType (keyType, valueType) -> |         | DictionaryType (keyType, valueType) -> | ||||||
|             node |             node | ||||||
|             |> asObject propertyName |             |> asObject propertyName | ||||||
|             |> SynExpr.pipeThroughFunction ( |             |> SynExpr.pipeThroughFunction ( | ||||||
|                 SynExpr.applyFunction |                 SynExpr.CreateApp ( | ||||||
|                     (SynExpr.createLongIdent [ "Seq" ; "map" ]) |                     SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]), | ||||||
|                     (dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)) |                     dictionaryMapper (parseKeyString keyType) (parseNode None options valueType) | ||||||
|  |                 ) | ||||||
|             ) |             ) | ||||||
|             |> SynExpr.pipeThroughFunction ( |             |> SynExpr.pipeThroughFunction ( | ||||||
|                 SynExpr.applyFunction |                 SynExpr.CreateApp ( | ||||||
|                     (SynExpr.createLongIdent [ "Seq" ; "map" ]) |                     SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]), | ||||||
|                     (SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ]) |                     SynExpr.CreateLongIdent ( | ||||||
|  |                         SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "KeyValuePair" ] | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|             ) |             ) | ||||||
|             |> SynExpr.pipeThroughFunction ( |             |> SynExpr.pipeThroughFunction ( | ||||||
|                 SynExpr.createLongIdent [ "System" ; "Collections" ; "Generic" ; "Dictionary" ] |                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Collections" ; "Generic" ; "Dictionary" ]) | ||||||
|             ) |             ) | ||||||
|         | IReadOnlyDictionaryType (keyType, valueType) -> |         | IReadOnlyDictionaryType (keyType, valueType) -> | ||||||
|             node |             node | ||||||
|             |> asObject propertyName |             |> asObject propertyName | ||||||
|             |> SynExpr.pipeThroughFunction ( |             |> SynExpr.pipeThroughFunction ( | ||||||
|                 SynExpr.applyFunction |                 SynExpr.CreateApp ( | ||||||
|                     (SynExpr.createLongIdent [ "Seq" ; "map" ]) |                     SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]), | ||||||
|                     (dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)) |                     dictionaryMapper (parseKeyString keyType) (parseNode None options valueType) | ||||||
|                 ) |                 ) | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createIdent "readOnlyDict") |             ) | ||||||
|  |             |> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "readOnlyDict" ])) | ||||||
|         | MapType (keyType, valueType) -> |         | MapType (keyType, valueType) -> | ||||||
|             node |             node | ||||||
|             |> asObject propertyName |             |> asObject propertyName | ||||||
|             |> SynExpr.pipeThroughFunction ( |             |> SynExpr.pipeThroughFunction ( | ||||||
|                 SynExpr.applyFunction |                 SynExpr.CreateApp ( | ||||||
|                     (SynExpr.createLongIdent [ "Seq" ; "map" ]) |                     SynExpr.CreateLongIdent (SynLongIdent.Create [ "Seq" ; "map" ]), | ||||||
|                     (dictionaryMapper (parseKeyString keyType) (parseNode None options valueType)) |                     dictionaryMapper (parseKeyString keyType) (parseNode None options valueType) | ||||||
|                 ) |                 ) | ||||||
|             |> SynExpr.pipeThroughFunction (SynExpr.createLongIdent [ "Map" ; "ofSeq" ]) |             ) | ||||||
|         | BigInt -> |             |> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Map" ; "ofSeq" ])) | ||||||
|             node |  | ||||||
|             |> SynExpr.callMethod "ToJsonString" |  | ||||||
|             |> SynExpr.paren |  | ||||||
|             |> SynExpr.applyFunction (SynExpr.createLongIdent [ "System" ; "Numerics" ; "BigInteger" ; "Parse" ]) |  | ||||||
|         | _ -> |         | _ -> | ||||||
|             // Let's just hope that we've also got our own type annotation! |             // Let's just hope that we've also got our own type annotation! | ||||||
|             let typeName = |             let typeName = | ||||||
| @@ -276,8 +327,9 @@ module internal JsonParseGenerator = | |||||||
|     /// propertyName is probably a string literal, but it could be a [<Literal>] variable |     /// propertyName is probably a string literal, but it could be a [<Literal>] variable | ||||||
|     /// The result of this function is the body of a let-binding (not including the LHS of that let-binding). |     /// The result of this function is the body of a let-binding (not including the LHS of that let-binding). | ||||||
|     let createParseRhs (options : JsonParseOption) (propertyName : SynExpr) (fieldType : SynType) : SynExpr = |     let createParseRhs (options : JsonParseOption) (propertyName : SynExpr) (fieldType : SynType) : SynExpr = | ||||||
|         let objectToParse = SynExpr.createIdent "node" |> SynExpr.index propertyName |         SynExpr.CreateIdentString "node" | ||||||
|         parseNode (Some propertyName) options fieldType objectToParse |         |> SynExpr.index propertyName | ||||||
|  |         |> parseNode (Some propertyName) options fieldType | ||||||
|  |  | ||||||
|     let isJsonNumberHandling (literal : LongIdent) : bool = |     let isJsonNumberHandling (literal : LongIdent) : bool = | ||||||
|         match List.rev literal |> List.map (fun ident -> ident.idText) with |         match List.rev literal |> List.map (fun ident -> ident.idText) with | ||||||
| @@ -288,57 +340,66 @@ module internal JsonParseGenerator = | |||||||
|         | [ _ ; "JsonNumberHandling" ; "Serialization" ; "Json" ; "Text" ; "System" ] -> true |         | [ _ ; "JsonNumberHandling" ; "Serialization" ; "Json" ; "Text" ; "System" ] -> true | ||||||
|         | _ -> false |         | _ -> false | ||||||
|  |  | ||||||
|     /// `populateNode` will be inserted before we return the `node` variable. |     let createMaker (spec : JsonParseOutputSpec) (typeName : LongIdent) (fields : SynField list) = | ||||||
|     /// |         let xmlDoc = PreXmlDoc.Create " Parse from a JSON node." | ||||||
|     /// That is, we give you access to a `JsonNode` called `node`, |  | ||||||
|     /// and you must return a `typeName`. |  | ||||||
|     let scaffolding (spec : JsonParseOutputSpec) (typeName : LongIdent) (functionBody : SynExpr) : SynModuleDecl = |  | ||||||
|         let xmlDoc = PreXmlDoc.create "Parse from a JSON node." |  | ||||||
|  |  | ||||||
|         let returnInfo = SynType.createLongIdent typeName |         let returnInfo = | ||||||
|  |             SynBindingReturnInfo.Create (SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName)) | ||||||
|  |  | ||||||
|         let inputArg = "node" |         let inputArg = Ident.Create "node" | ||||||
|         let functionName = Ident.create "jsonParse" |         let functionName = Ident.Create "jsonParse" | ||||||
|  |  | ||||||
|         let arg = |  | ||||||
|             SynPat.named inputArg |  | ||||||
|             |> SynPat.annotateType (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]) |  | ||||||
|  |  | ||||||
|  |         let inputVal = | ||||||
|  |             let memberFlags = | ||||||
|                 if spec.ExtensionMethods then |                 if spec.ExtensionMethods then | ||||||
|             let binding = |                     { | ||||||
|                 SynBinding.basic [ functionName ] [ arg ] functionBody |                         SynMemberFlags.IsInstance = false | ||||||
|                 |> SynBinding.withXmlDoc xmlDoc |                         SynMemberFlags.IsDispatchSlot = false | ||||||
|                 |> SynBinding.withReturnAnnotation returnInfo |                         SynMemberFlags.IsOverrideOrExplicitImpl = false | ||||||
|                 |> SynMemberDefn.staticMember |                         SynMemberFlags.IsFinal = false | ||||||
|  |                         SynMemberFlags.GetterOrSetterIsCompilerGenerated = false | ||||||
|             let componentInfo = |                         SynMemberFlags.MemberKind = SynMemberKind.Member | ||||||
|                 SynComponentInfo.createLong typeName |                     } | ||||||
|                 |> SynComponentInfo.withDocString (PreXmlDoc.create "Extension methods for JSON parsing") |                     |> Some | ||||||
|  |  | ||||||
|             let containingType = |  | ||||||
|                 SynTypeDefnRepr.augmentation () |  | ||||||
|                 |> SynTypeDefn.create componentInfo |  | ||||||
|                 |> SynTypeDefn.withMemberDefns [ binding ] |  | ||||||
|  |  | ||||||
|             SynModuleDecl.Types ([ containingType ], range0) |  | ||||||
|                 else |                 else | ||||||
|             SynBinding.basic [ functionName ] [ arg ] functionBody |                     None | ||||||
|             |> SynBinding.withXmlDoc xmlDoc |  | ||||||
|             |> SynBinding.withReturnAnnotation returnInfo |  | ||||||
|             |> SynModuleDecl.createLet |  | ||||||
|  |  | ||||||
|     let getParseOptions (fieldAttrs : SynAttribute list) = |             let thisIdOpt = if spec.ExtensionMethods then None else Some inputArg | ||||||
|         (JsonParseOption.None, fieldAttrs) |  | ||||||
|  |             SynValData.SynValData ( | ||||||
|  |                 memberFlags, | ||||||
|  |                 SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty), | ||||||
|  |                 thisIdOpt | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         let assignments = | ||||||
|  |             fields | ||||||
|  |             |> List.map (fun (SynField (attrs, _, id, fieldType, _, _, _, _, _)) -> | ||||||
|  |                 let id = | ||||||
|  |                     match id with | ||||||
|  |                     | None -> failwith "didn't get an ID on field" | ||||||
|  |                     | Some id -> id | ||||||
|  |  | ||||||
|  |                 let attrs = attrs |> List.collect (fun l -> l.Attributes) | ||||||
|  |  | ||||||
|  |                 let propertyNameAttr = | ||||||
|  |                     attrs | ||||||
|  |                     |> List.tryFind (fun attr -> | ||||||
|  |                         attr.TypeName.AsString.EndsWith ("JsonPropertyName", StringComparison.Ordinal) | ||||||
|  |                     ) | ||||||
|  |  | ||||||
|  |                 let options = | ||||||
|  |                     (JsonParseOption.None, attrs) | ||||||
|                     ||> List.fold (fun options attr -> |                     ||> List.fold (fun options attr -> | ||||||
|             if |                         if attr.TypeName.AsString.EndsWith ("JsonNumberHandling", StringComparison.Ordinal) then | ||||||
|                 (SynLongIdent.toString attr.TypeName) |  | ||||||
|                     .EndsWith ("JsonNumberHandling", StringComparison.Ordinal) |  | ||||||
|             then |  | ||||||
|                             let qualifiedEnumValue = |                             let qualifiedEnumValue = | ||||||
|                                 match SynExpr.stripOptionalParen attr.ArgExpr with |                                 match SynExpr.stripOptionalParen attr.ArgExpr with | ||||||
|                     | SynExpr.LongIdent (_, SynLongIdent (ident, _, _), _, _) when isJsonNumberHandling ident -> |                                 | SynExpr.LongIdent (_, SynLongIdent (ident, _, _), _, _) when | ||||||
|  |                                     isJsonNumberHandling ident | ||||||
|  |                                     -> | ||||||
|                                     // Make sure it's fully qualified |                                     // Make sure it's fully qualified | ||||||
|                         SynExpr.createLongIdent |                                     SynExpr.CreateLongIdent ( | ||||||
|  |                                         SynLongIdent.Create | ||||||
|                                             [ |                                             [ | ||||||
|                                                 "System" |                                                 "System" | ||||||
|                                                 "Text" |                                                 "Text" | ||||||
| @@ -347,6 +408,7 @@ module internal JsonParseGenerator = | |||||||
|                                                 "JsonNumberHandling" |                                                 "JsonNumberHandling" | ||||||
|                                                 "AllowReadingFromString" |                                                 "AllowReadingFromString" | ||||||
|                                             ] |                                             ] | ||||||
|  |                                     ) | ||||||
|                                 | _ -> attr.ArgExpr |                                 | _ -> attr.ArgExpr | ||||||
|  |  | ||||||
|                             { |                             { | ||||||
| @@ -356,139 +418,160 @@ module internal JsonParseGenerator = | |||||||
|                             options |                             options | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|     let createRecordMaker (spec : JsonParseOutputSpec) (fields : SynFieldData<Ident> list) = |  | ||||||
|         let assignments = |  | ||||||
|             fields |  | ||||||
|             |> List.mapi (fun i fieldData -> |  | ||||||
|                 let propertyNameAttr = |  | ||||||
|                     fieldData.Attrs |  | ||||||
|                     |> List.tryFind (fun attr -> |  | ||||||
|                         (SynLongIdent.toString attr.TypeName) |  | ||||||
|                             .EndsWith ("JsonPropertyName", StringComparison.Ordinal) |  | ||||||
|                     ) |  | ||||||
|  |  | ||||||
|                 let options = getParseOptions fieldData.Attrs |  | ||||||
|  |  | ||||||
|                 let propertyName = |                 let propertyName = | ||||||
|                     match propertyNameAttr with |                     match propertyNameAttr with | ||||||
|                     | None -> |                     | None -> | ||||||
|                         let sb = StringBuilder fieldData.Ident.idText.Length |                         let sb = StringBuilder id.idText.Length | ||||||
|  |                         sb.Append (Char.ToLowerInvariant id.idText.[0]) |> ignore | ||||||
|  |  | ||||||
|                         sb.Append (Char.ToLowerInvariant fieldData.Ident.idText.[0]) |                         if id.idText.Length > 1 then | ||||||
|                         |> ignore<StringBuilder> |                             sb.Append id.idText.[1..] |> ignore | ||||||
|  |  | ||||||
|                         if fieldData.Ident.idText.Length > 1 then |                         sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst | ||||||
|                             sb.Append (fieldData.Ident.idText.Substring 1) |> ignore<StringBuilder> |  | ||||||
|  |  | ||||||
|                         sb.ToString () |> SynExpr.CreateConst |  | ||||||
|                     | Some name -> name.ArgExpr |                     | Some name -> name.ArgExpr | ||||||
|  |  | ||||||
|                 createParseRhs options propertyName fieldData.Type |                 let pattern = | ||||||
|                 |> SynBinding.basic [ Ident.create $"arg_%i{i}" ] [] |                     SynPat.LongIdent ( | ||||||
|  |                         SynLongIdent.CreateFromLongIdent [ id ], | ||||||
|  |                         None, | ||||||
|  |                         None, | ||||||
|  |                         SynArgPats.Empty, | ||||||
|  |                         None, | ||||||
|  |                         range0 | ||||||
|  |                     ) | ||||||
|  |  | ||||||
|  |                 SynBinding.Let ( | ||||||
|  |                     isInline = false, | ||||||
|  |                     isMutable = false, | ||||||
|  |                     expr = createParseRhs options propertyName fieldType, | ||||||
|  |                     valData = inputVal, | ||||||
|  |                     pattern = pattern | ||||||
|  |                 ) | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         let finalConstruction = |         let finalConstruction = | ||||||
|             fields |             fields | ||||||
|             |> List.mapi (fun i fieldData -> |             |> List.map (fun (SynField (_, _, id, _, _, _, _, _, _)) -> | ||||||
|                 (SynLongIdent.createI fieldData.Ident, true), Some (SynExpr.createIdent $"arg_%i{i}") |                 let id = | ||||||
|  |                     match id with | ||||||
|  |                     | None -> failwith "Expected record field to have an identifying name" | ||||||
|  |                     | Some id -> id | ||||||
|  |  | ||||||
|  |                 (SynLongIdent.CreateFromLongIdent [ id ], true), | ||||||
|  |                 Some (SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ id ])) | ||||||
|             ) |             ) | ||||||
|             |> AstHelper.instantiateRecord |             |> AstHelper.instantiateRecord | ||||||
|  |  | ||||||
|  |         let assignments = | ||||||
|             (finalConstruction, assignments) |             (finalConstruction, assignments) | ||||||
|         ||> List.fold (fun final assignment -> SynExpr.createLet [ assignment ] final) |             ||> List.fold (fun final assignment -> | ||||||
|  |                 SynExpr.LetOrUse ( | ||||||
|  |                     false, | ||||||
|  |                     false, | ||||||
|  |                     [ assignment ], | ||||||
|  |                     final, | ||||||
|  |                     range0, | ||||||
|  |                     { | ||||||
|  |                         InKeyword = None | ||||||
|  |                     } | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |  | ||||||
|     let createUnionMaker (spec : JsonParseOutputSpec) (typeName : LongIdent) (fields : UnionCase<Ident> list) = |         let pattern = | ||||||
|         fields |             SynPat.LongIdent ( | ||||||
|         |> List.map (fun case -> |                 SynLongIdent.CreateFromLongIdent [ functionName ], | ||||||
|             let propertyName = JsonSerializeGenerator.getPropertyName case.Ident case.Attrs |                 None, | ||||||
|  |                 None, | ||||||
|  |                 SynArgPats.Pats | ||||||
|  |                     [ | ||||||
|  |                         SynPat.CreateTyped ( | ||||||
|  |                             SynPat.CreateNamed inputArg, | ||||||
|  |                             SynType.LongIdent ( | ||||||
|  |                                 SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ] | ||||||
|  |                             ) | ||||||
|  |                         ) | ||||||
|  |                         |> SynPat.CreateParen | ||||||
|  |                     ], | ||||||
|  |                 None, | ||||||
|  |                 range0 | ||||||
|  |             ) | ||||||
|  |  | ||||||
|             let body = |         if spec.ExtensionMethods then | ||||||
|                 if case.Fields.IsEmpty then |             let binding = | ||||||
|                     SynExpr.createLongIdent' (typeName @ [ case.Ident ]) |                 SynBinding.SynBinding ( | ||||||
|  |                     None, | ||||||
|  |                     SynBindingKind.Normal, | ||||||
|  |                     false, | ||||||
|  |                     false, | ||||||
|  |                     [], | ||||||
|  |                     xmlDoc, | ||||||
|  |                     inputVal, | ||||||
|  |                     pattern, | ||||||
|  |                     Some returnInfo, | ||||||
|  |                     assignments, | ||||||
|  |                     range0, | ||||||
|  |                     DebugPointAtBinding.NoneAtInvisible, | ||||||
|  |                     { | ||||||
|  |                         LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0) | ||||||
|  |                         InlineKeyword = None | ||||||
|  |                         EqualsRange = Some range0 | ||||||
|  |                     } | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |             let mem = SynMemberDefn.Member (binding, range0) | ||||||
|  |  | ||||||
|  |             let containingType = | ||||||
|  |                 SynTypeDefn.SynTypeDefn ( | ||||||
|  |                     SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"), | ||||||
|  |                     SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0), | ||||||
|  |                     [ mem ], | ||||||
|  |                     None, | ||||||
|  |                     range0, | ||||||
|  |                     { | ||||||
|  |                         LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0 | ||||||
|  |                         EqualsRange = None | ||||||
|  |                         WithKeyword = None | ||||||
|  |                     } | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |             SynModuleDecl.Types ([ containingType ], range0) | ||||||
|         else |         else | ||||||
|                     case.Fields |             let binding = | ||||||
|                     |> List.map (fun field -> |                 SynBinding.Let ( | ||||||
|                         let propertyName = JsonSerializeGenerator.getPropertyName field.Ident field.Attrs |                     isInline = false, | ||||||
|                         let options = getParseOptions field.Attrs |                     isMutable = false, | ||||||
|                         createParseRhs options propertyName field.Type |                     xmldoc = xmlDoc, | ||||||
|  |                     returnInfo = returnInfo, | ||||||
|  |                     expr = assignments, | ||||||
|  |                     valData = inputVal, | ||||||
|  |                     pattern = pattern | ||||||
|                 ) |                 ) | ||||||
|                     |> SynExpr.tuple |  | ||||||
|                     |> SynExpr.applyFunction (SynExpr.createLongIdent' (typeName @ [ case.Ident ])) |  | ||||||
|                     |> SynExpr.createLet |  | ||||||
|                         [ |  | ||||||
|                             SynExpr.index (SynExpr.CreateConst "data") (SynExpr.createIdent "node") |  | ||||||
|                             |> assertNotNull (SynExpr.CreateConst "data") |  | ||||||
|                             |> SynBinding.basic [ Ident.create "node" ] [] |  | ||||||
|                         ] |  | ||||||
|  |  | ||||||
|             match propertyName with |             SynModuleDecl.CreateLet [ binding ] | ||||||
|             | SynExpr.Const (synConst, _) -> |  | ||||||
|                 SynMatchClause.SynMatchClause ( |  | ||||||
|                     SynPat.createConst synConst, |  | ||||||
|                     None, |  | ||||||
|                     body, |  | ||||||
|                     range0, |  | ||||||
|                     DebugPointAtTarget.Yes, |  | ||||||
|                     { |  | ||||||
|                         ArrowRange = Some range0 |  | ||||||
|                         BarRange = Some range0 |  | ||||||
|                     } |  | ||||||
|                 ) |  | ||||||
|             | _ -> |  | ||||||
|                 SynMatchClause.create (SynPat.named "x") body |  | ||||||
|                 |> SynMatchClause.withWhere (SynExpr.equals (SynExpr.createIdent "x") propertyName) |  | ||||||
|         ) |  | ||||||
|         |> fun l -> |  | ||||||
|             l |  | ||||||
|             @ [ |  | ||||||
|                 let fail = |  | ||||||
|                     SynExpr.plus (SynExpr.CreateConst "Unrecognised 'type' field value: ") (SynExpr.createIdent "v") |  | ||||||
|                     |> SynExpr.paren |  | ||||||
|                     |> SynExpr.applyFunction (SynExpr.createIdent "failwith") |  | ||||||
|  |  | ||||||
|                 SynMatchClause.SynMatchClause ( |     let createRecordModule (namespaceId : LongIdent) (spec : JsonParseOutputSpec) (typeDefn : SynTypeDefn) = | ||||||
|                     SynPat.named "v", |  | ||||||
|                     None, |  | ||||||
|                     fail, |  | ||||||
|                     range0, |  | ||||||
|                     DebugPointAtTarget.Yes, |  | ||||||
|                     { |  | ||||||
|                         ArrowRange = Some range0 |  | ||||||
|                         BarRange = Some range0 |  | ||||||
|                     } |  | ||||||
|                 ) |  | ||||||
|             ] |  | ||||||
|         |> SynExpr.createMatch (SynExpr.createIdent "ty") |  | ||||||
|         |> SynExpr.createLet |  | ||||||
|             [ |  | ||||||
|                 let property = SynExpr.CreateConst "type" |  | ||||||
|  |  | ||||||
|                 SynExpr.createIdent "node" |  | ||||||
|                 |> SynExpr.index property |  | ||||||
|                 |> assertNotNull property |  | ||||||
|                 |> SynExpr.pipeThroughFunction ( |  | ||||||
|                     SynExpr.createLambda |  | ||||||
|                         "v" |  | ||||||
|                         (SynExpr.callGenericMethod "GetValue" [ Ident.create "string" ] (SynExpr.createIdent "v")) |  | ||||||
|                 ) |  | ||||||
|                 |> SynBinding.basic [ Ident.create "ty" ] [] |  | ||||||
|             ] |  | ||||||
|  |  | ||||||
|     let createModule (namespaceId : LongIdent) (spec : JsonParseOutputSpec) (typeDefn : SynTypeDefn) = |  | ||||||
|         let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) = |         let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) = | ||||||
|             typeDefn |             typeDefn | ||||||
|  |  | ||||||
|         let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, _access, _)) = |         let (SynComponentInfo (_attributes, _typeParams, _constraints, recordId, _, _preferPostfix, _access, _)) = | ||||||
|             synComponentInfo |             synComponentInfo | ||||||
|  |  | ||||||
|  |         match synTypeDefnRepr with | ||||||
|  |         | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, recordFields, _recordRange), _) -> | ||||||
|  |  | ||||||
|  |             let decls = [ createMaker spec recordId recordFields ] | ||||||
|  |  | ||||||
|             let attributes = |             let attributes = | ||||||
|                 if spec.ExtensionMethods then |                 if spec.ExtensionMethods then | ||||||
|                 [ SynAttribute.autoOpen ] |                     [ SynAttributeList.Create SynAttribute.autoOpen ] | ||||||
|                 else |                 else | ||||||
|                 [ SynAttribute.requireQualifiedAccess ; SynAttribute.compilationRepresentation ] |                     [ | ||||||
|  |                         SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ()) | ||||||
|  |                         SynAttributeList.Create SynAttribute.compilationRepresentation | ||||||
|  |                     ] | ||||||
|  |  | ||||||
|             let xmlDoc = |             let xmlDoc = | ||||||
|             let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "." |                 let fullyQualified = recordId |> Seq.map (fun i -> i.idText) |> String.concat "." | ||||||
|  |  | ||||||
|                 let description = |                 let description = | ||||||
|                     if spec.ExtensionMethods then |                     if spec.ExtensionMethods then | ||||||
| @@ -497,50 +580,30 @@ module internal JsonParseGenerator = | |||||||
|                         "methods" |                         "methods" | ||||||
|  |  | ||||||
|                 $" Module containing JSON parsing %s{description} for the %s{fullyQualified} type" |                 $" Module containing JSON parsing %s{description} for the %s{fullyQualified} type" | ||||||
|             |> PreXmlDoc.create |                 |> PreXmlDoc.Create | ||||||
|  |  | ||||||
|             let moduleName = |             let moduleName = | ||||||
|                 if spec.ExtensionMethods then |                 if spec.ExtensionMethods then | ||||||
|                 match ident with |                     match recordId with | ||||||
|                     | [] -> failwith "unexpectedly got an empty identifier for record name" |                     | [] -> failwith "unexpectedly got an empty identifier for record name" | ||||||
|                 | ident -> |                     | recordId -> | ||||||
|                         let expanded = |                         let expanded = | ||||||
|                         List.last ident |                             List.last recordId | ||||||
|                             |> fun i -> i.idText |                             |> fun i -> i.idText | ||||||
|                             |> fun s -> s + "JsonParseExtension" |                             |> fun s -> s + "JsonParseExtension" | ||||||
|                         |> Ident.create |                             |> Ident.Create | ||||||
|  |  | ||||||
|                     List.take (List.length ident - 1) ident @ [ expanded ] |                         List.take (List.length recordId - 1) recordId @ [ expanded ] | ||||||
|                 else |                 else | ||||||
|                 ident |                     recordId | ||||||
|  |  | ||||||
|             let info = |             let info = | ||||||
|             SynComponentInfo.createLong moduleName |                 SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc) | ||||||
|             |> SynComponentInfo.withDocString xmlDoc |  | ||||||
|             |> SynComponentInfo.addAttributes attributes |  | ||||||
|  |  | ||||||
|         let decl = |             let mdl = SynModuleDecl.CreateNestedModule (info, decls) | ||||||
|             match synTypeDefnRepr with |  | ||||||
|             | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, fields, _range), _) -> |  | ||||||
|                 fields |> List.map SynField.extractWithIdent |> createRecordMaker spec |  | ||||||
|             | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (_accessibility, cases, _range), _) -> |  | ||||||
|                 let optionGet (i : Ident option) = |  | ||||||
|                     match i with |  | ||||||
|                     | None -> failwith "WoofWare.Myriad requires union cases to have identifiers on each field." |  | ||||||
|                     | Some i -> i |  | ||||||
|  |  | ||||||
|                 cases |             SynModuleOrNamespace.CreateNamespace (namespaceId, decls = [ mdl ]) | ||||||
|                 |> List.map SynUnionCase.extract |         | _ -> failwithf "Not a record type" | ||||||
|                 |> List.map (UnionCase.mapIdentFields optionGet) |  | ||||||
|                 |> createUnionMaker spec ident |  | ||||||
|             | _ -> failwithf "Not a record or union type" |  | ||||||
|  |  | ||||||
|         [ scaffolding spec ident decl ] |  | ||||||
|         |> SynModuleDecl.nestedModule info |  | ||||||
|         |> List.singleton |  | ||||||
|         |> SynModuleOrNamespace.createNamespace namespaceId |  | ||||||
|  |  | ||||||
| open Myriad.Core |  | ||||||
|  |  | ||||||
| /// Myriad generator that provides a method (possibly an extension method) for a record type, | /// Myriad generator that provides a method (possibly an extension method) for a record type, | ||||||
| /// containing a JSON parse function. | /// containing a JSON parse function. | ||||||
| @@ -554,20 +617,10 @@ type JsonParseGenerator () = | |||||||
|             let ast, _ = |             let ast, _ = | ||||||
|                 Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head |                 Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head | ||||||
|  |  | ||||||
|             let recordsAndUnions = |             let records = Ast.extractRecords ast | ||||||
|                 Ast.extractTypeDefn ast |  | ||||||
|                 |> List.map (fun (name, defns) -> |  | ||||||
|                     defns |  | ||||||
|                     |> List.choose (fun defn -> |  | ||||||
|                         if Ast.isRecord defn then Some defn |  | ||||||
|                         elif Ast.isDu defn then Some defn |  | ||||||
|                         else None |  | ||||||
|                     ) |  | ||||||
|                     |> fun defns -> name, defns |  | ||||||
|                 ) |  | ||||||
|  |  | ||||||
|             let namespaceAndTypes = |             let namespaceAndRecords = | ||||||
|                 recordsAndUnions |                 records | ||||||
|                 |> List.choose (fun (ns, types) -> |                 |> List.choose (fun (ns, types) -> | ||||||
|                     types |                     types | ||||||
|                     |> List.choose (fun typeDef -> |                     |> List.choose (fun typeDef -> | ||||||
| @@ -595,9 +648,13 @@ type JsonParseGenerator () = | |||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|             let modules = |             let modules = | ||||||
|                 namespaceAndTypes |                 namespaceAndRecords | ||||||
|                 |> List.collect (fun (ns, types) -> |                 |> List.collect (fun (ns, records) -> | ||||||
|                     types |> List.map (fun (ty, spec) -> JsonParseGenerator.createModule ns spec ty) |                     records | ||||||
|  |                     |> List.map (fun (record, spec) -> | ||||||
|  |                         let recordModule = JsonParseGenerator.createRecordModule ns spec record | ||||||
|  |                         recordModule | ||||||
|  |                     ) | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|             Output.Ast modules |             Output.Ast modules | ||||||
|   | |||||||
| @@ -3,6 +3,9 @@ namespace WoofWare.Myriad.Plugins | |||||||
| open System | open System | ||||||
| open System.Text | open System.Text | ||||||
| open Fantomas.FCS.Syntax | open Fantomas.FCS.Syntax | ||||||
|  | open Fantomas.FCS.SyntaxTrivia | ||||||
|  | open Fantomas.FCS.Xml | ||||||
|  | open Myriad.Core | ||||||
|  |  | ||||||
| type internal JsonSerializeOutputSpec = | type internal JsonSerializeOutputSpec = | ||||||
|     { |     { | ||||||
| @@ -12,6 +15,7 @@ type internal JsonSerializeOutputSpec = | |||||||
| [<RequireQualifiedAccess>] | [<RequireQualifiedAccess>] | ||||||
| module internal JsonSerializeGenerator = | module internal JsonSerializeGenerator = | ||||||
|     open Fantomas.FCS.Text.Range |     open Fantomas.FCS.Text.Range | ||||||
|  |     open Myriad.Core.Ast | ||||||
|  |  | ||||||
|     /// Given `input.Ident`, for example, choose how to add it to the ambient `node`. |     /// Given `input.Ident`, for example, choose how to add it to the ambient `node`. | ||||||
|     /// The result is a line like `(fun ident -> InnerType.toJsonNode ident)` or `(fun ident -> JsonValue.Create ident)`. |     /// The result is a line like `(fun ident -> InnerType.toJsonNode ident)` or `(fun ident -> JsonValue.Create ident)`. | ||||||
| @@ -26,7 +30,9 @@ module internal JsonSerializeGenerator = | |||||||
|         | Uri -> |         | Uri -> | ||||||
|             // JsonValue.Create<type> |             // JsonValue.Create<type> | ||||||
|             SynExpr.TypeApp ( |             SynExpr.TypeApp ( | ||||||
|                 SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ], |                 SynExpr.CreateLongIdent ( | ||||||
|  |                     SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ] | ||||||
|  |                 ), | ||||||
|                 range0, |                 range0, | ||||||
|                 [ fieldType ], |                 [ fieldType ], | ||||||
|                 [], |                 [], | ||||||
| @@ -36,24 +42,39 @@ module internal JsonSerializeGenerator = | |||||||
|             ) |             ) | ||||||
|         | OptionType ty -> |         | OptionType ty -> | ||||||
|             // fun field -> match field with | None -> JsonValue.Create null | Some v -> {serializeNode ty} field |             // fun field -> match field with | None -> JsonValue.Create null | Some v -> {serializeNode ty} field | ||||||
|             let noneClause = |             SynExpr.CreateMatch ( | ||||||
|  |                 SynExpr.CreateIdentString "field", | ||||||
|  |                 [ | ||||||
|  |                     SynMatchClause.Create ( | ||||||
|  |                         SynPat.CreateLongIdent (SynLongIdent.CreateString "None", []), | ||||||
|  |                         None, | ||||||
|                         // The absolutely galaxy-brained implementation of JsonValue has `JsonValue.Parse "null"` |                         // The absolutely galaxy-brained implementation of JsonValue has `JsonValue.Parse "null"` | ||||||
|                         // identically equal to null. We have to work around this later, but we might as well just |                         // identically equal to null. We have to work around this later, but we might as well just | ||||||
|                         // be efficient here and whip up the null directly. |                         // be efficient here and whip up the null directly. | ||||||
|                 SynExpr.createNull () |                         SynExpr.CreateNull | ||||||
|                 |> SynExpr.upcast' (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]) |                         |> SynExpr.upcast' ( | ||||||
|                 |> SynMatchClause.create (SynPat.named "None") |                             SynType.CreateLongIdent ( | ||||||
|  |                                 SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ] | ||||||
|             let someClause = |                             ) | ||||||
|                 SynExpr.applyFunction (serializeNode ty) (SynExpr.createIdent "field") |                         ) | ||||||
|                 |> SynExpr.paren |  | ||||||
|                 |> SynExpr.upcast' (SynType.createLongIdent' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]) |  | ||||||
|                 |> SynMatchClause.create ( |  | ||||||
|                     SynPat.identWithArgs [ Ident.create "Some" ] (SynArgPats.create [ Ident.create "field" ]) |  | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|             [ noneClause ; someClause ] |                     SynMatchClause.Create ( | ||||||
|             |> SynExpr.createMatch (SynExpr.createIdent "field") |                         SynPat.CreateLongIdent ( | ||||||
|  |                             SynLongIdent.CreateString "Some", | ||||||
|  |                             [ SynPat.CreateNamed (Ident.Create "field") ] | ||||||
|  |                         ), | ||||||
|  |                         None, | ||||||
|  |                         SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "field") | ||||||
|  |                         |> SynExpr.CreateParen | ||||||
|  |                         |> SynExpr.upcast' ( | ||||||
|  |                             SynType.CreateLongIdent ( | ||||||
|  |                                 SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ] | ||||||
|  |                             ) | ||||||
|  |                         ) | ||||||
|  |                     ) | ||||||
|  |                 ] | ||||||
|  |             ) | ||||||
|             |> SynExpr.createLambda "field" |             |> SynExpr.createLambda "field" | ||||||
|         | ArrayType ty |         | ArrayType ty | ||||||
|         | ListType ty -> |         | ListType ty -> | ||||||
| @@ -61,69 +82,116 @@ module internal JsonSerializeGenerator = | |||||||
|             //     let arr = JsonArray () |             //     let arr = JsonArray () | ||||||
|             //     for mem in field do arr.Add ({serializeNode} mem) |             //     for mem in field do arr.Add ({serializeNode} mem) | ||||||
|             //     arr |             //     arr | ||||||
|  |             SynExpr.LetOrUse ( | ||||||
|  |                 false, | ||||||
|  |                 false, | ||||||
|  |                 [ | ||||||
|  |                     SynBinding.Let ( | ||||||
|  |                         pattern = SynPat.CreateNamed (Ident.Create "arr"), | ||||||
|  |                         expr = | ||||||
|  |                             SynExpr.CreateApp ( | ||||||
|  |                                 SynExpr.CreateLongIdent ( | ||||||
|  |                                     SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonArray" ] | ||||||
|  |                                 ), | ||||||
|  |                                 SynExpr.CreateConst SynConst.Unit | ||||||
|  |                             ) | ||||||
|  |                     ) | ||||||
|  |                 ], | ||||||
|  |                 SynExpr.CreateSequential | ||||||
|                     [ |                     [ | ||||||
|                         SynExpr.ForEach ( |                         SynExpr.ForEach ( | ||||||
|                             DebugPointAtFor.Yes range0, |                             DebugPointAtFor.Yes range0, | ||||||
|                             DebugPointAtInOrTo.Yes range0, |                             DebugPointAtInOrTo.Yes range0, | ||||||
|                             SeqExprOnly.SeqExprOnly false, |                             SeqExprOnly.SeqExprOnly false, | ||||||
|                             true, |                             true, | ||||||
|                     SynPat.named "mem", |                             SynPat.CreateNamed (Ident.Create "mem"), | ||||||
|                     SynExpr.createIdent "field", |                             SynExpr.CreateIdent (Ident.Create "field"), | ||||||
|                     SynExpr.applyFunction |                             SynExpr.CreateApp ( | ||||||
|                         (SynExpr.createLongIdent [ "arr" ; "Add" ]) |                                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "arr" ; "Add" ]), | ||||||
|                         (SynExpr.paren (SynExpr.applyFunction (serializeNode ty) (SynExpr.createIdent "mem"))), |                                 SynExpr.CreateParen ( | ||||||
|  |                                     SynExpr.CreateApp (serializeNode ty, SynExpr.CreateIdentString "mem") | ||||||
|  |                                 ) | ||||||
|  |                             ), | ||||||
|                             range0 |                             range0 | ||||||
|                         ) |                         ) | ||||||
|                 SynExpr.createIdent "arr" |                         SynExpr.CreateIdentString "arr" | ||||||
|             ] |                     ], | ||||||
|             |> SynExpr.sequential |                 range0, | ||||||
|             |> SynExpr.createLet |                 { | ||||||
|                 [ |                     InKeyword = None | ||||||
|                     SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonArray" ] |                 } | ||||||
|                     |> SynExpr.applyTo (SynExpr.CreateConst ()) |             ) | ||||||
|                     |> SynBinding.basic [ Ident.create "arr" ] [] |  | ||||||
|                 ] |  | ||||||
|             |> SynExpr.createLambda "field" |             |> SynExpr.createLambda "field" | ||||||
|         | IDictionaryType (_keyType, valueType) |         | IDictionaryType (keyType, valueType) | ||||||
|         | DictionaryType (_keyType, valueType) |         | DictionaryType (keyType, valueType) | ||||||
|         | IReadOnlyDictionaryType (_keyType, valueType) |         | IReadOnlyDictionaryType (keyType, valueType) | ||||||
|         | MapType (_keyType, valueType) -> |         | MapType (keyType, valueType) -> | ||||||
|             // fun field -> |             // fun field -> | ||||||
|             //    let ret = JsonObject () |             //    let ret = JsonObject () | ||||||
|             //    for (KeyValue(key, value)) in field do |             //    for (KeyValue(key, value)) in field do | ||||||
|             //        ret.Add (key.ToString (), {serializeNode} value) |             //        ret.Add (key.ToString (), {serializeNode} value) | ||||||
|             //    ret |             //    ret | ||||||
|  |             SynExpr.LetOrUse ( | ||||||
|  |                 false, | ||||||
|  |                 false, | ||||||
|  |                 [ | ||||||
|  |                     SynBinding.Let ( | ||||||
|  |                         pattern = SynPat.CreateNamed (Ident.Create "ret"), | ||||||
|  |                         expr = | ||||||
|  |                             SynExpr.CreateApp ( | ||||||
|  |                                 SynExpr.CreateLongIdent ( | ||||||
|  |                                     SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ] | ||||||
|  |                                 ), | ||||||
|  |                                 SynExpr.CreateConst SynConst.Unit | ||||||
|  |                             ) | ||||||
|  |                     ) | ||||||
|  |                 ], | ||||||
|  |                 SynExpr.CreateSequential | ||||||
|                     [ |                     [ | ||||||
|                         SynExpr.ForEach ( |                         SynExpr.ForEach ( | ||||||
|                             DebugPointAtFor.Yes range0, |                             DebugPointAtFor.Yes range0, | ||||||
|                             DebugPointAtInOrTo.Yes range0, |                             DebugPointAtInOrTo.Yes range0, | ||||||
|                             SeqExprOnly.SeqExprOnly false, |                             SeqExprOnly.SeqExprOnly false, | ||||||
|                             true, |                             true, | ||||||
|                     SynPat.paren ( |                             SynPat.CreateParen ( | ||||||
|                         SynPat.identWithArgs |                                 SynPat.CreateLongIdent ( | ||||||
|                             [ Ident.create "KeyValue" ] |                                     SynLongIdent.CreateString "KeyValue", | ||||||
|                             (SynArgPats.create [ Ident.create "key" ; Ident.create "value" ]) |  | ||||||
|                     ), |  | ||||||
|                     SynExpr.createIdent "field", |  | ||||||
|                     SynExpr.applyFunction |  | ||||||
|                         (SynExpr.createLongIdent [ "ret" ; "Add" ]) |  | ||||||
|                         (SynExpr.tuple |  | ||||||
|                                     [ |                                     [ | ||||||
|                                 SynExpr.createLongIdent [ "key" ; "ToString" ] |                                         SynPat.CreateParen ( | ||||||
|                                 |> SynExpr.applyTo (SynExpr.CreateConst ()) |                                             SynPat.Tuple ( | ||||||
|                                 SynExpr.applyFunction (serializeNode valueType) (SynExpr.createIdent "value") |                                                 false, | ||||||
|                             ]), |                                                 [ | ||||||
|  |                                                     SynPat.CreateNamed (Ident.Create "key") | ||||||
|  |                                                     SynPat.CreateNamed (Ident.Create "value") | ||||||
|  |                                                 ], | ||||||
|  |                                                 [ range0 ], | ||||||
|                                                 range0 |                                                 range0 | ||||||
|                                             ) |                                             ) | ||||||
|                 SynExpr.createIdent "ret" |                                         ) | ||||||
|                                     ] |                                     ] | ||||||
|             |> SynExpr.sequential |                                 ) | ||||||
|             |> SynExpr.createLet |                             ), | ||||||
|  |                             SynExpr.CreateIdent (Ident.Create "field"), | ||||||
|  |                             SynExpr.CreateApp ( | ||||||
|  |                                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "ret" ; "Add" ]), | ||||||
|  |                                 SynExpr.CreateParenedTuple | ||||||
|                                     [ |                                     [ | ||||||
|                     SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ] |                                         SynExpr.CreateApp ( | ||||||
|                     |> SynExpr.applyTo (SynExpr.CreateConst ()) |                                             SynExpr.CreateLongIdent (SynLongIdent.Create [ "key" ; "ToString" ]), | ||||||
|                     |> SynBinding.basic [ Ident.create "ret" ] [] |                                             SynExpr.CreateConst SynConst.Unit | ||||||
|  |                                         ) | ||||||
|  |                                         SynExpr.CreateApp (serializeNode valueType, SynExpr.CreateIdentString "value") | ||||||
|                                     ] |                                     ] | ||||||
|  |                             ), | ||||||
|  |                             range0 | ||||||
|  |                         ) | ||||||
|  |                         SynExpr.CreateIdentString "ret" | ||||||
|  |                     ], | ||||||
|  |                 range0, | ||||||
|  |                 { | ||||||
|  |                     InKeyword = None | ||||||
|  |                 } | ||||||
|  |             ) | ||||||
|             |> SynExpr.createLambda "field" |             |> SynExpr.createLambda "field" | ||||||
|         | _ -> |         | _ -> | ||||||
|             // {type}.toJsonNode |             // {type}.toJsonNode | ||||||
| @@ -132,189 +200,213 @@ module internal JsonSerializeGenerator = | |||||||
|                 | SynType.LongIdent ident -> ident.LongIdent |                 | SynType.LongIdent ident -> ident.LongIdent | ||||||
|                 | _ -> failwith $"Unrecognised type: %+A{fieldType}" |                 | _ -> failwith $"Unrecognised type: %+A{fieldType}" | ||||||
|  |  | ||||||
|             SynExpr.createLongIdent' (typeName @ [ Ident.create "toJsonNode" ]) |             SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent (typeName @ [ Ident.Create "toJsonNode" ])) | ||||||
|  |  | ||||||
|     /// propertyName is probably a string literal, but it could be a [<Literal>] variable |     /// propertyName is probably a string literal, but it could be a [<Literal>] variable | ||||||
|     /// `node.Add ({propertyName}, {toJsonNode})` |     /// `node.Add ({propertyName}, {toJsonNode})` | ||||||
|     let createSerializeRhsRecord (propertyName : SynExpr) (fieldId : Ident) (fieldType : SynType) : SynExpr = |     let createSerializeRhs (propertyName : SynExpr) (fieldId : Ident) (fieldType : SynType) : SynExpr = | ||||||
|  |         let func = SynExpr.CreateLongIdent (SynLongIdent.Create [ "node" ; "Add" ]) | ||||||
|  |  | ||||||
|  |         let args = | ||||||
|  |             SynExpr.CreateParenedTuple | ||||||
|                 [ |                 [ | ||||||
|                     propertyName |                     propertyName | ||||||
|             SynExpr.applyFunction |                     SynExpr.CreateApp ( | ||||||
|                 (serializeNode fieldType) |                         serializeNode fieldType, | ||||||
|                 (SynExpr.createLongIdent' [ Ident.create "input" ; fieldId ]) |                         SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ Ident.Create "input" ; fieldId ]) | ||||||
|  |                     ) | ||||||
|                 ] |                 ] | ||||||
|         |> SynExpr.tuple |  | ||||||
|         |> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ]) |  | ||||||
|  |  | ||||||
|     let getPropertyName (fieldId : Ident) (attrs : SynAttribute list) : SynExpr = |         SynExpr.CreateApp (func, args) | ||||||
|  |  | ||||||
|  |     let createMaker (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (fields : SynField list) = | ||||||
|  |         let xmlDoc = PreXmlDoc.Create " Serialize to a JSON node" | ||||||
|  |  | ||||||
|  |         let returnInfo = | ||||||
|  |             SynBindingReturnInfo.Create ( | ||||||
|  |                 SynType.LongIdent (SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]) | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         let inputArg = Ident.Create "input" | ||||||
|  |         let functionName = Ident.Create "toJsonNode" | ||||||
|  |  | ||||||
|  |         let inputVal = | ||||||
|  |             let memberFlags = | ||||||
|  |                 if spec.ExtensionMethods then | ||||||
|  |                     { | ||||||
|  |                         SynMemberFlags.IsInstance = false | ||||||
|  |                         SynMemberFlags.IsDispatchSlot = false | ||||||
|  |                         SynMemberFlags.IsOverrideOrExplicitImpl = false | ||||||
|  |                         SynMemberFlags.IsFinal = false | ||||||
|  |                         SynMemberFlags.GetterOrSetterIsCompilerGenerated = false | ||||||
|  |                         SynMemberFlags.MemberKind = SynMemberKind.Member | ||||||
|  |                     } | ||||||
|  |                     |> Some | ||||||
|  |                 else | ||||||
|  |                     None | ||||||
|  |  | ||||||
|  |             let thisIdOpt = if spec.ExtensionMethods then None else Some inputArg | ||||||
|  |  | ||||||
|  |             SynValData.SynValData ( | ||||||
|  |                 memberFlags, | ||||||
|  |                 SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty), | ||||||
|  |                 thisIdOpt | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         let assignments = | ||||||
|  |             fields | ||||||
|  |             |> List.map (fun (SynField (attrs, _, id, fieldType, _, _, _, _, _)) -> | ||||||
|  |                 let id = | ||||||
|  |                     match id with | ||||||
|  |                     | None -> failwith "didn't get an ID on field" | ||||||
|  |                     | Some id -> id | ||||||
|  |  | ||||||
|  |                 let attrs = attrs |> List.collect (fun l -> l.Attributes) | ||||||
|  |  | ||||||
|                 let propertyNameAttr = |                 let propertyNameAttr = | ||||||
|                     attrs |                     attrs | ||||||
|                     |> List.tryFind (fun attr -> |                     |> List.tryFind (fun attr -> | ||||||
|                 (SynLongIdent.toString attr.TypeName) |                         attr.TypeName.AsString.EndsWith ("JsonPropertyName", StringComparison.Ordinal) | ||||||
|                     .EndsWith ("JsonPropertyName", StringComparison.Ordinal) |  | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|  |                 let propertyName = | ||||||
|                     match propertyNameAttr with |                     match propertyNameAttr with | ||||||
|                     | None -> |                     | None -> | ||||||
|             let sb = StringBuilder fieldId.idText.Length |                         let sb = StringBuilder id.idText.Length | ||||||
|             sb.Append (Char.ToLowerInvariant fieldId.idText.[0]) |> ignore |                         sb.Append (Char.ToLowerInvariant id.idText.[0]) |> ignore | ||||||
|  |  | ||||||
|             if fieldId.idText.Length > 1 then |                         if id.idText.Length > 1 then | ||||||
|                 sb.Append fieldId.idText.[1..] |> ignore |                             sb.Append id.idText.[1..] |> ignore | ||||||
|  |  | ||||||
|             sb.ToString () |> SynExpr.CreateConst |                         sb.ToString () |> SynConst.CreateString |> SynExpr.CreateConst | ||||||
|                     | Some name -> name.ArgExpr |                     | Some name -> name.ArgExpr | ||||||
|  |  | ||||||
|     /// `populateNode` will be inserted before we return the `node` variable. |  | ||||||
|     /// |  | ||||||
|     /// That is, we give you access to a `JsonObject` called `node`, |  | ||||||
|     /// and you have access to a variable `inputArgName` which is of type `typeName`. |  | ||||||
|     /// Your job is to provide a `populateNode` expression which has the side effect |  | ||||||
|     /// of mutating `node` to faithfully reflect the value of `inputArgName`. |  | ||||||
|     let scaffolding |  | ||||||
|         (spec : JsonSerializeOutputSpec) |  | ||||||
|         (typeName : LongIdent) |  | ||||||
|         (inputArgName : Ident) |  | ||||||
|         (populateNode : SynExpr) |  | ||||||
|         : SynModuleDecl |  | ||||||
|         = |  | ||||||
|         let xmlDoc = PreXmlDoc.create "Serialize to a JSON node" |  | ||||||
|  |  | ||||||
|         let returnInfo = |  | ||||||
|             SynLongIdent.createS' [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ] |  | ||||||
|             |> SynType.LongIdent |  | ||||||
|  |  | ||||||
|         let functionName = Ident.create "toJsonNode" |  | ||||||
|  |  | ||||||
|         let assignments = |  | ||||||
|             [ |  | ||||||
|                 populateNode |  | ||||||
|                 SynExpr.Upcast (SynExpr.createIdent "node", SynType.Anon range0, range0) |  | ||||||
|             ] |  | ||||||
|             |> SynExpr.sequential |  | ||||||
|             |> SynExpr.createLet |  | ||||||
|                 [ |  | ||||||
|                     SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ] |  | ||||||
|                     |> SynExpr.applyTo (SynExpr.CreateConst ()) |  | ||||||
|                     |> SynBinding.basic [ Ident.create "node" ] [] |  | ||||||
|                 ] |  | ||||||
|  |  | ||||||
|         let pattern = |  | ||||||
|             SynPat.namedI inputArgName |  | ||||||
|             |> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create typeName)) |  | ||||||
|  |  | ||||||
|         if spec.ExtensionMethods then |  | ||||||
|             let componentInfo = |  | ||||||
|                 SynComponentInfo.createLong typeName |  | ||||||
|                 |> SynComponentInfo.withDocString (PreXmlDoc.create "Extension methods for JSON parsing") |  | ||||||
|  |  | ||||||
|             let memberDef = |  | ||||||
|                 assignments |  | ||||||
|                 |> SynBinding.basic [ functionName ] [ pattern ] |  | ||||||
|                 |> SynBinding.withXmlDoc xmlDoc |  | ||||||
|                 |> SynBinding.withReturnAnnotation returnInfo |  | ||||||
|                 |> SynMemberDefn.staticMember |  | ||||||
|  |  | ||||||
|             let containingType = |  | ||||||
|                 SynTypeDefnRepr.augmentation () |  | ||||||
|                 |> SynTypeDefn.create componentInfo |  | ||||||
|                 |> SynTypeDefn.withMemberDefns [ memberDef ] |  | ||||||
|  |  | ||||||
|             SynModuleDecl.Types ([ containingType ], range0) |  | ||||||
|         else |  | ||||||
|             assignments |  | ||||||
|             |> SynBinding.basic [ functionName ] [ pattern ] |  | ||||||
|             |> SynBinding.withReturnAnnotation returnInfo |  | ||||||
|             |> SynBinding.withXmlDoc xmlDoc |  | ||||||
|             |> SynModuleDecl.createLet |  | ||||||
|  |  | ||||||
|     let recordModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (fields : SynField list) = |  | ||||||
|         let inputArg = Ident.create "input" |  | ||||||
|         let fields = fields |> List.map SynField.extractWithIdent |  | ||||||
|  |  | ||||||
|         fields |  | ||||||
|         |> List.map (fun fieldData -> |  | ||||||
|             let propertyName = getPropertyName fieldData.Ident fieldData.Attrs |  | ||||||
|             createSerializeRhsRecord propertyName fieldData.Ident fieldData.Type |  | ||||||
|         ) |  | ||||||
|         |> SynExpr.sequential |  | ||||||
|         |> fun expr -> SynExpr.Do (expr, range0) |  | ||||||
|         |> scaffolding spec typeName inputArg |  | ||||||
|  |  | ||||||
|     let unionModule (spec : JsonSerializeOutputSpec) (typeName : LongIdent) (cases : SynUnionCase list) = |  | ||||||
|         let inputArg = Ident.create "input" |  | ||||||
|         let fields = cases |> List.map SynUnionCase.extract |  | ||||||
|  |  | ||||||
|         fields |  | ||||||
|         |> List.map (fun unionCase -> |  | ||||||
|             let propertyName = getPropertyName unionCase.Ident unionCase.Attrs |  | ||||||
|  |  | ||||||
|             let caseNames = unionCase.Fields |> List.mapi (fun i _ -> Ident.create $"arg%i{i}") |  | ||||||
|  |  | ||||||
|             let argPats = SynArgPats.create caseNames |  | ||||||
|  |  | ||||||
|                 let pattern = |                 let pattern = | ||||||
|                     SynPat.LongIdent ( |                     SynPat.LongIdent ( | ||||||
|                     SynLongIdent.create (typeName @ [ unionCase.Ident ]), |                         SynLongIdent.CreateFromLongIdent [ id ], | ||||||
|                         None, |                         None, | ||||||
|                         None, |                         None, | ||||||
|                     argPats, |                         SynArgPats.Empty, | ||||||
|                         None, |                         None, | ||||||
|                         range0 |                         range0 | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|             let typeLine = |                 createSerializeRhs propertyName id fieldType | ||||||
|                 [ |  | ||||||
|                     SynExpr.CreateConst "type" |  | ||||||
|                     SynExpr.applyFunction |  | ||||||
|                         (SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonValue" ; "Create" ]) |  | ||||||
|                         propertyName |  | ||||||
|                 ] |  | ||||||
|                 |> SynExpr.tuple |  | ||||||
|                 |> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ]) |  | ||||||
|  |  | ||||||
|             let dataNode = |  | ||||||
|                 SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ] |  | ||||||
|                 |> SynExpr.applyTo (SynExpr.CreateConst ()) |  | ||||||
|                 |> SynBinding.basic [ Ident.create "dataNode" ] [] |  | ||||||
|  |  | ||||||
|             let dataBindings = |  | ||||||
|                 (unionCase.Fields, caseNames) |  | ||||||
|                 ||> List.zip |  | ||||||
|                 |> List.map (fun (fieldData, caseName) -> |  | ||||||
|                     let propertyName = getPropertyName (Option.get fieldData.Ident) fieldData.Attrs |  | ||||||
|  |  | ||||||
|                     let node = |  | ||||||
|                         SynExpr.applyFunction (serializeNode fieldData.Type) (SynExpr.createIdent' caseName) |  | ||||||
|  |  | ||||||
|                     [ propertyName ; node ] |  | ||||||
|                     |> SynExpr.tuple |  | ||||||
|                     |> SynExpr.applyFunction (SynExpr.createLongIdent [ "dataNode" ; "Add" ]) |  | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|             let assignToNode = |         let finalConstruction = | ||||||
|                 [ SynExpr.CreateConst "data" ; SynExpr.createIdent "dataNode" ] |             fields | ||||||
|                 |> SynExpr.tuple |             |> List.map (fun (SynField (_, _, id, _, _, _, _, _, _)) -> | ||||||
|                 |> SynExpr.applyFunction (SynExpr.createLongIdent [ "node" ; "Add" ]) |                 let id = | ||||||
|  |                     match id with | ||||||
|  |                     | None -> failwith "Expected record field to have an identifying name" | ||||||
|  |                     | Some id -> id | ||||||
|  |  | ||||||
|             let dataNode = |                 (SynLongIdent.CreateFromLongIdent [ id ], true), | ||||||
|                 SynExpr.sequential (dataBindings @ [ assignToNode ]) |                 Some (SynExpr.CreateLongIdent (SynLongIdent.CreateFromLongIdent [ id ])) | ||||||
|                 |> SynExpr.createLet [ dataNode ] |  | ||||||
|  |  | ||||||
|             let action = |  | ||||||
|                 [ |  | ||||||
|                     yield typeLine |  | ||||||
|                     if not dataBindings.IsEmpty then |  | ||||||
|                         yield dataNode |  | ||||||
|                 ] |  | ||||||
|                 |> SynExpr.sequential |  | ||||||
|  |  | ||||||
|             SynMatchClause.create pattern action |  | ||||||
|             ) |             ) | ||||||
|         |> SynExpr.createMatch (SynExpr.createIdent' inputArg) |             |> AstHelper.instantiateRecord | ||||||
|         |> scaffolding spec typeName inputArg |  | ||||||
|  |  | ||||||
|     let createModule |         let assignments = assignments |> SynExpr.CreateSequential | ||||||
|  |  | ||||||
|  |         let assignments = | ||||||
|  |             SynExpr.LetOrUse ( | ||||||
|  |                 false, | ||||||
|  |                 false, | ||||||
|  |                 [ | ||||||
|  |                     SynBinding.Let ( | ||||||
|  |                         pattern = SynPat.CreateNamed (Ident.Create "node"), | ||||||
|  |                         expr = | ||||||
|  |                             SynExpr.CreateApp ( | ||||||
|  |                                 SynExpr.CreateLongIdent ( | ||||||
|  |                                     SynLongIdent.Create [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ] | ||||||
|  |                                 ), | ||||||
|  |                                 SynExpr.CreateConst SynConst.Unit | ||||||
|  |                             ) | ||||||
|  |                     ) | ||||||
|  |                 ], | ||||||
|  |                 SynExpr.CreateSequential | ||||||
|  |                     [ | ||||||
|  |                         SynExpr.Do (assignments, range0) | ||||||
|  |                         SynExpr.Upcast (SynExpr.CreateIdentString "node", SynType.Anon range0, range0) | ||||||
|  |                     ], | ||||||
|  |                 range0, | ||||||
|  |                 { | ||||||
|  |                     InKeyword = None | ||||||
|  |                 } | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         let pattern = | ||||||
|  |             SynPat.LongIdent ( | ||||||
|  |                 SynLongIdent.CreateFromLongIdent [ functionName ], | ||||||
|  |                 None, | ||||||
|  |                 None, | ||||||
|  |                 SynArgPats.Pats | ||||||
|  |                     [ | ||||||
|  |                         SynPat.CreateTyped ( | ||||||
|  |                             SynPat.CreateNamed inputArg, | ||||||
|  |                             SynType.LongIdent (SynLongIdent.CreateFromLongIdent typeName) | ||||||
|  |                         ) | ||||||
|  |                         |> SynPat.CreateParen | ||||||
|  |                     ], | ||||||
|  |                 None, | ||||||
|  |                 range0 | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         if spec.ExtensionMethods then | ||||||
|  |             let binding = | ||||||
|  |                 SynBinding.SynBinding ( | ||||||
|  |                     None, | ||||||
|  |                     SynBindingKind.Normal, | ||||||
|  |                     false, | ||||||
|  |                     false, | ||||||
|  |                     [], | ||||||
|  |                     xmlDoc, | ||||||
|  |                     inputVal, | ||||||
|  |                     pattern, | ||||||
|  |                     Some returnInfo, | ||||||
|  |                     assignments, | ||||||
|  |                     range0, | ||||||
|  |                     DebugPointAtBinding.NoneAtInvisible, | ||||||
|  |                     { | ||||||
|  |                         LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0) | ||||||
|  |                         InlineKeyword = None | ||||||
|  |                         EqualsRange = Some range0 | ||||||
|  |                     } | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |             let mem = SynMemberDefn.Member (binding, range0) | ||||||
|  |  | ||||||
|  |             let containingType = | ||||||
|  |                 SynTypeDefn.SynTypeDefn ( | ||||||
|  |                     SynComponentInfo.Create (typeName, xmldoc = PreXmlDoc.Create " Extension methods for JSON parsing"), | ||||||
|  |                     SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0), | ||||||
|  |                     [ mem ], | ||||||
|  |                     None, | ||||||
|  |                     range0, | ||||||
|  |                     { | ||||||
|  |                         LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0 | ||||||
|  |                         EqualsRange = None | ||||||
|  |                         WithKeyword = None | ||||||
|  |                     } | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |             SynModuleDecl.Types ([ containingType ], range0) | ||||||
|  |         else | ||||||
|  |             let binding = | ||||||
|  |                 SynBinding.Let ( | ||||||
|  |                     isInline = false, | ||||||
|  |                     isMutable = false, | ||||||
|  |                     xmldoc = xmlDoc, | ||||||
|  |                     returnInfo = returnInfo, | ||||||
|  |                     expr = assignments, | ||||||
|  |                     valData = inputVal, | ||||||
|  |                     pattern = pattern | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |             SynModuleDecl.CreateLet [ binding ] | ||||||
|  |  | ||||||
|  |     let createRecordModule | ||||||
|         (namespaceId : LongIdent) |         (namespaceId : LongIdent) | ||||||
|         (opens : SynOpenDeclTarget list) |         (opens : SynOpenDeclTarget list) | ||||||
|         (spec : JsonSerializeOutputSpec) |         (spec : JsonSerializeOutputSpec) | ||||||
| @@ -323,17 +415,25 @@ module internal JsonSerializeGenerator = | |||||||
|         let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) = |         let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) = | ||||||
|             typeDefn |             typeDefn | ||||||
|  |  | ||||||
|         let (SynComponentInfo (_attributes, _typeParams, _constraints, ident, _, _preferPostfix, _access, _)) = |         let (SynComponentInfo (_attributes, _typeParams, _constraints, recordId, _, _preferPostfix, _access, _)) = | ||||||
|             synComponentInfo |             synComponentInfo | ||||||
|  |  | ||||||
|  |         match synTypeDefnRepr with | ||||||
|  |         | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, recordFields, _recordRange), _) -> | ||||||
|  |  | ||||||
|  |             let decls = [ createMaker spec recordId recordFields ] | ||||||
|  |  | ||||||
|             let attributes = |             let attributes = | ||||||
|                 if spec.ExtensionMethods then |                 if spec.ExtensionMethods then | ||||||
|                 [ SynAttribute.autoOpen ] |                     [ SynAttributeList.Create SynAttribute.autoOpen ] | ||||||
|                 else |                 else | ||||||
|                 [ SynAttribute.requireQualifiedAccess ; SynAttribute.compilationRepresentation ] |                     [ | ||||||
|  |                         SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ()) | ||||||
|  |                         SynAttributeList.Create SynAttribute.compilationRepresentation | ||||||
|  |                     ] | ||||||
|  |  | ||||||
|             let xmlDoc = |             let xmlDoc = | ||||||
|             let fullyQualified = ident |> Seq.map (fun i -> i.idText) |> String.concat "." |                 let fullyQualified = recordId |> Seq.map (fun i -> i.idText) |> String.concat "." | ||||||
|  |  | ||||||
|                 let description = |                 let description = | ||||||
|                     if spec.ExtensionMethods then |                     if spec.ExtensionMethods then | ||||||
| @@ -342,43 +442,33 @@ module internal JsonSerializeGenerator = | |||||||
|                         "methods" |                         "methods" | ||||||
|  |  | ||||||
|                 $" Module containing JSON serializing %s{description} for the %s{fullyQualified} type" |                 $" Module containing JSON serializing %s{description} for the %s{fullyQualified} type" | ||||||
|             |> PreXmlDoc.create |                 |> PreXmlDoc.Create | ||||||
|  |  | ||||||
|             let moduleName = |             let moduleName = | ||||||
|                 if spec.ExtensionMethods then |                 if spec.ExtensionMethods then | ||||||
|                 match ident with |                     match recordId with | ||||||
|                 | [] -> failwith "unexpectedly got an empty identifier for type name" |                     | [] -> failwith "unexpectedly got an empty identifier for record name" | ||||||
|                 | ident -> |                     | recordId -> | ||||||
|                         let expanded = |                         let expanded = | ||||||
|                         List.last ident |                             List.last recordId | ||||||
|                             |> fun i -> i.idText |                             |> fun i -> i.idText | ||||||
|                             |> fun s -> s + "JsonSerializeExtension" |                             |> fun s -> s + "JsonSerializeExtension" | ||||||
|                         |> Ident.create |                             |> Ident.Create | ||||||
|  |  | ||||||
|                     List.take (List.length ident - 1) ident @ [ expanded ] |                         List.take (List.length recordId - 1) recordId @ [ expanded ] | ||||||
|                 else |                 else | ||||||
|                 ident |                     recordId | ||||||
|  |  | ||||||
|             let info = |             let info = | ||||||
|             SynComponentInfo.createLong moduleName |                 SynComponentInfo.Create (moduleName, attributes = attributes, xmldoc = xmlDoc) | ||||||
|             |> SynComponentInfo.addAttributes attributes |  | ||||||
|             |> SynComponentInfo.withDocString xmlDoc |  | ||||||
|  |  | ||||||
|         let decls = |             let mdl = SynModuleDecl.CreateNestedModule (info, decls) | ||||||
|             match synTypeDefnRepr with |  | ||||||
|             | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (_accessibility, recordFields, _range), _) -> |  | ||||||
|                 [ recordModule spec ident recordFields ] |  | ||||||
|             | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (_accessibility, unionFields, _range), _) -> |  | ||||||
|                 [ unionModule spec ident unionFields ] |  | ||||||
|             | _ -> failwithf "Only record types currently supported." |  | ||||||
|  |  | ||||||
|         [ |             SynModuleOrNamespace.CreateNamespace ( | ||||||
|             yield! opens |> List.map SynModuleDecl.openAny |                 namespaceId, | ||||||
|             yield SynModuleDecl.nestedModule info decls |                 decls = (opens |> List.map SynModuleDecl.CreateOpen) @ [ mdl ] | ||||||
|         ] |             ) | ||||||
|         |> SynModuleOrNamespace.createNamespace namespaceId |         | _ -> failwithf "Not a record type" | ||||||
|  |  | ||||||
| open Myriad.Core |  | ||||||
|  |  | ||||||
| /// Myriad generator that provides a method (possibly an extension method) for a record type, | /// Myriad generator that provides a method (possibly an extension method) for a record type, | ||||||
| /// containing a JSON serialization function. | /// containing a JSON serialization function. | ||||||
| @@ -392,20 +482,10 @@ type JsonSerializeGenerator () = | |||||||
|             let ast, _ = |             let ast, _ = | ||||||
|                 Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head |                 Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head | ||||||
|  |  | ||||||
|             let recordsAndUnions = |             let records = Ast.extractRecords ast | ||||||
|                 Ast.extractTypeDefn ast |  | ||||||
|                 |> List.map (fun (name, defns) -> |  | ||||||
|                     defns |  | ||||||
|                     |> List.choose (fun defn -> |  | ||||||
|                         if Ast.isRecord defn then Some defn |  | ||||||
|                         elif Ast.isDu defn then Some defn |  | ||||||
|                         else None |  | ||||||
|                     ) |  | ||||||
|                     |> fun defns -> name, defns |  | ||||||
|                 ) |  | ||||||
|  |  | ||||||
|             let namespaceAndTypes = |             let namespaceAndRecords = | ||||||
|                 recordsAndUnions |                 records | ||||||
|                 |> List.choose (fun (ns, types) -> |                 |> List.choose (fun (ns, types) -> | ||||||
|                     types |                     types | ||||||
|                     |> List.choose (fun typeDef -> |                     |> List.choose (fun typeDef -> | ||||||
| @@ -435,10 +515,13 @@ type JsonSerializeGenerator () = | |||||||
|             let opens = AstHelper.extractOpens ast |             let opens = AstHelper.extractOpens ast | ||||||
|  |  | ||||||
|             let modules = |             let modules = | ||||||
|                 namespaceAndTypes |                 namespaceAndRecords | ||||||
|                 |> List.collect (fun (ns, types) -> |                 |> List.collect (fun (ns, records) -> | ||||||
|                     types |                     records | ||||||
|                     |> List.map (fun (ty, spec) -> JsonSerializeGenerator.createModule ns opens spec ty) |                     |> List.map (fun (record, spec) -> | ||||||
|  |                         let recordModule = JsonSerializeGenerator.createRecordModule ns opens spec record | ||||||
|  |                         recordModule | ||||||
|  |                     ) | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|             Output.Ast modules |             Output.Ast modules | ||||||
|   | |||||||
| @@ -1,30 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal Primitives = |  | ||||||
|     /// Given e.g. "byte", returns "System.Byte". |  | ||||||
|     let qualifyType (typeName : string) : LongIdent option = |  | ||||||
|         match typeName with |  | ||||||
|         | "float32" |  | ||||||
|         | "single" -> [ "System" ; "Single" ] |> Some |  | ||||||
|         | "float" |  | ||||||
|         | "double" -> [ "System" ; "Double" ] |> Some |  | ||||||
|         | "byte" |  | ||||||
|         | "uint8" -> [ "System" ; "Byte" ] |> Some |  | ||||||
|         | "sbyte" |  | ||||||
|         | "int8" -> [ "System" ; "SByte" ] |> Some |  | ||||||
|         | "int16" -> [ "System" ; "Int16" ] |> Some |  | ||||||
|         | "int" |  | ||||||
|         | "int32" -> [ "System" ; "Int32" ] |> Some |  | ||||||
|         | "int64" -> [ "System" ; "Int64" ] |> Some |  | ||||||
|         | "uint16" -> [ "System" ; "UInt16" ] |> Some |  | ||||||
|         | "uint" |  | ||||||
|         | "uint32" -> [ "System" ; "UInt32" ] |> Some |  | ||||||
|         | "uint64" -> [ "System" ; "UInt64" ] |> Some |  | ||||||
|         | "char" -> [ "System" ; "Char" ] |> Some |  | ||||||
|         | "decimal" -> [ "System" ; "Decimal" ] |> Some |  | ||||||
|         | _ -> None |  | ||||||
|         |> Option.map (List.map (fun i -> (Ident (i, range0)))) |  | ||||||
| @@ -1,11 +1,14 @@ | |||||||
| namespace WoofWare.Myriad.Plugins | namespace WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax | open Fantomas.FCS.Syntax | ||||||
|  | open Fantomas.FCS.SyntaxTrivia | ||||||
| open Fantomas.FCS.Xml | open Fantomas.FCS.Xml | ||||||
|  | open Myriad.Core | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] | [<RequireQualifiedAccess>] | ||||||
| module internal RemoveOptionsGenerator = | module internal RemoveOptionsGenerator = | ||||||
|     open Fantomas.FCS.Text.Range |     open Fantomas.FCS.Text.Range | ||||||
|  |     open Myriad.Core.Ast | ||||||
|  |  | ||||||
|     let private removeOption (s : SynField) : SynField = |     let private removeOption (s : SynField) : SynField = | ||||||
|         let (SynField.SynField (synAttributeLists, |         let (SynField.SynField (synAttributeLists, | ||||||
| @@ -44,7 +47,7 @@ module internal RemoveOptionsGenerator = | |||||||
|         (fields : SynField list) |         (fields : SynField list) | ||||||
|         = |         = | ||||||
|         let fields : SynField list = fields |> List.map removeOption |         let fields : SynField list = fields |> List.map removeOption | ||||||
|         let name = Ident.create "Short" |         let name = Ident.Create "Short" | ||||||
|  |  | ||||||
|         let record = |         let record = | ||||||
|             { |             { | ||||||
| @@ -60,51 +63,94 @@ module internal RemoveOptionsGenerator = | |||||||
|  |  | ||||||
|         SynModuleDecl.Types ([ typeDecl ], range0) |         SynModuleDecl.Types ([ typeDecl ], range0) | ||||||
|  |  | ||||||
|     let createMaker (withOptionsType : LongIdent) (withoutOptionsType : LongIdent) (fields : SynFieldData<Ident> list) = |     let createMaker (withOptionsType : LongIdent) (withoutOptionsType : LongIdent) (fields : SynField list) = | ||||||
|         let xmlDoc = PreXmlDoc.create "Remove the optional members of the input." |         let xmlDoc = PreXmlDoc.Create " Remove the optional members of the input." | ||||||
|  |  | ||||||
|         let inputArg = Ident.create "input" |         let returnInfo = | ||||||
|         let functionName = Ident.create "shorten" |             SynBindingReturnInfo.Create (SynType.LongIdent (SynLongIdent.CreateFromLongIdent withOptionsType)) | ||||||
|  |  | ||||||
|  |         let inputArg = Ident.Create "input" | ||||||
|  |         let functionName = Ident.Create "shorten" | ||||||
|  |  | ||||||
|  |         let inputVal = | ||||||
|  |             SynValData.SynValData ( | ||||||
|  |                 None, | ||||||
|  |                 SynValInfo.SynValInfo ([ [ SynArgInfo.CreateId functionName ] ], SynArgInfo.Empty), | ||||||
|  |                 Some inputArg | ||||||
|  |             ) | ||||||
|  |  | ||||||
|         let body = |         let body = | ||||||
|             fields |             fields | ||||||
|             |> List.map (fun fieldData -> |             |> List.map (fun (SynField (_, _, id, fieldType, _, _, _, _, _)) -> | ||||||
|  |                 let id = | ||||||
|  |                     match id with | ||||||
|  |                     | None -> failwith "Expected record field to have an identifying name" | ||||||
|  |                     | Some id -> id | ||||||
|  |  | ||||||
|                 let accessor = |                 let accessor = | ||||||
|  |                     SynExpr.LongIdent (false, SynLongIdent ([ inputArg ; id ], [ range0 ], []), None, range0) | ||||||
|  |  | ||||||
|  |                 let body = | ||||||
|  |                     match fieldType with | ||||||
|  |                     | OptionType _ -> | ||||||
|  |                         SynExpr.CreateApp ( | ||||||
|  |                             SynExpr.CreateAppInfix ( | ||||||
|                                 SynExpr.LongIdent ( |                                 SynExpr.LongIdent ( | ||||||
|                                     false, |                                     false, | ||||||
|                         SynLongIdent ([ inputArg ; fieldData.Ident ], [ range0 ], []), |                                     SynLongIdent.SynLongIdent ( | ||||||
|  |                                         [ Ident.Create "op_PipeRight" ], | ||||||
|  |                                         [], | ||||||
|  |                                         [ Some (IdentTrivia.OriginalNotation "|>") ] | ||||||
|  |                                     ), | ||||||
|  |                                     None, | ||||||
|  |                                     range0 | ||||||
|  |                                 ), | ||||||
|  |                                 accessor | ||||||
|  |                             ), | ||||||
|  |                             SynExpr.CreateApp ( | ||||||
|  |                                 SynExpr.CreateLongIdent (SynLongIdent.CreateString "Option.defaultWith"), | ||||||
|  |                                 SynExpr.CreateLongIdent ( | ||||||
|  |                                     SynLongIdent.CreateFromLongIdent ( | ||||||
|  |                                         withoutOptionsType @ [ Ident.Create (sprintf "Default%s" id.idText) ] | ||||||
|  |                                     ) | ||||||
|  |                                 ) | ||||||
|  |                             ) | ||||||
|  |                         ) | ||||||
|  |                     | _ -> accessor | ||||||
|  |  | ||||||
|  |                 (SynLongIdent.CreateFromLongIdent [ id ], true), Some body | ||||||
|  |             ) | ||||||
|  |             |> AstHelper.instantiateRecord | ||||||
|  |  | ||||||
|  |         let pattern = | ||||||
|  |             SynPat.LongIdent ( | ||||||
|  |                 SynLongIdent.CreateFromLongIdent [ functionName ], | ||||||
|  |                 None, | ||||||
|  |                 None, | ||||||
|  |                 SynArgPats.Pats | ||||||
|  |                     [ | ||||||
|  |                         SynPat.CreateTyped ( | ||||||
|  |                             SynPat.CreateNamed inputArg, | ||||||
|  |                             SynType.LongIdent (SynLongIdent.CreateFromLongIdent withoutOptionsType) | ||||||
|  |                         ) | ||||||
|  |                         |> SynPat.CreateParen | ||||||
|  |                     ], | ||||||
|                 None, |                 None, | ||||||
|                 range0 |                 range0 | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|                 let body = |         let binding = | ||||||
|                     match fieldData.Type with |             SynBinding.Let ( | ||||||
|                     | OptionType _ -> |                 isInline = false, | ||||||
|                         accessor |                 isMutable = false, | ||||||
|                         |> SynExpr.pipeThroughFunction ( |                 xmldoc = xmlDoc, | ||||||
|                             SynExpr.applyFunction |                 returnInfo = returnInfo, | ||||||
|                                 (SynExpr.createLongIdent [ "Option" ; "defaultWith" ]) |                 expr = body, | ||||||
|                                 (SynExpr.createLongIdent' ( |                 valData = inputVal, | ||||||
|                                     withoutOptionsType |                 pattern = pattern | ||||||
|                                     @ [ Ident.create (sprintf "Default%s" fieldData.Ident.idText) ] |  | ||||||
|                                 )) |  | ||||||
|             ) |             ) | ||||||
|                     | _ -> accessor |  | ||||||
|  |  | ||||||
|                 (SynLongIdent.createI fieldData.Ident, true), Some body |         SynModuleDecl.CreateLet [ binding ] | ||||||
|             ) |  | ||||||
|             |> AstHelper.instantiateRecord |  | ||||||
|  |  | ||||||
|         SynBinding.basic |  | ||||||
|             [ functionName ] |  | ||||||
|             [ |  | ||||||
|                 SynPat.named inputArg.idText |  | ||||||
|                 |> SynPat.annotateType (SynType.LongIdent (SynLongIdent.create withoutOptionsType)) |  | ||||||
|             ] |  | ||||||
|             body |  | ||||||
|         |> SynBinding.withXmlDoc xmlDoc |  | ||||||
|         |> SynBinding.withReturnAnnotation (SynType.LongIdent (SynLongIdent.create withOptionsType)) |  | ||||||
|         |> SynModuleDecl.createLet |  | ||||||
|  |  | ||||||
|     let createRecordModule (namespaceId : LongIdent) (typeDefn : SynTypeDefn) = |     let createRecordModule (namespaceId : LongIdent) (typeDefn : SynTypeDefn) = | ||||||
|         let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) = |         let (SynTypeDefn (synComponentInfo, synTypeDefnRepr, _members, _implicitCtor, _, _)) = | ||||||
| @@ -114,13 +160,18 @@ module internal RemoveOptionsGenerator = | |||||||
|             synComponentInfo |             synComponentInfo | ||||||
|  |  | ||||||
|         match synTypeDefnRepr with |         match synTypeDefnRepr with | ||||||
|         | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (accessibility, fields, _range), _) -> |         | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (accessibility, recordFields, _recordRange), _) -> | ||||||
|             let fieldData = fields |> List.map SynField.extractWithIdent |  | ||||||
|  |  | ||||||
|             let decls = |             let decls = | ||||||
|                 [ |                 [ | ||||||
|                     createType (Some doc) accessibility typeParams fields |                     createType (Some doc) accessibility typeParams recordFields | ||||||
|                     createMaker [ Ident.create "Short" ] recordId fieldData |                     createMaker [ Ident.Create "Short" ] recordId recordFields | ||||||
|  |                 ] | ||||||
|  |  | ||||||
|  |             let attributes = | ||||||
|  |                 [ | ||||||
|  |                     SynAttributeList.Create (SynAttribute.RequireQualifiedAccess ()) | ||||||
|  |                     SynAttributeList.Create SynAttribute.compilationRepresentation | ||||||
|                 ] |                 ] | ||||||
|  |  | ||||||
|             let xmlDoc = |             let xmlDoc = | ||||||
| @@ -128,21 +179,16 @@ module internal RemoveOptionsGenerator = | |||||||
|                 |> Seq.map (fun i -> i.idText) |                 |> Seq.map (fun i -> i.idText) | ||||||
|                 |> String.concat "." |                 |> String.concat "." | ||||||
|                 |> sprintf " Module containing an option-truncated version of the %s type" |                 |> sprintf " Module containing an option-truncated version of the %s type" | ||||||
|                 |> PreXmlDoc.create |                 |> PreXmlDoc.Create | ||||||
|  |  | ||||||
|             let info = |             let info = | ||||||
|                 SynComponentInfo.createLong recordId |                 SynComponentInfo.Create (recordId, attributes = attributes, xmldoc = xmlDoc) | ||||||
|                 |> SynComponentInfo.withDocString xmlDoc |  | ||||||
|                 |> SynComponentInfo.addAttributes [ SynAttribute.compilationRepresentation ] |  | ||||||
|                 |> SynComponentInfo.addAttributes [ SynAttribute.requireQualifiedAccess ] |  | ||||||
|  |  | ||||||
|             SynModuleDecl.nestedModule info decls |             let mdl = SynModuleDecl.CreateNestedModule (info, decls) | ||||||
|             |> List.singleton |  | ||||||
|             |> SynModuleOrNamespace.createNamespace namespaceId |             SynModuleOrNamespace.CreateNamespace (namespaceId, decls = [ mdl ]) | ||||||
|         | _ -> failwithf "Not a record type" |         | _ -> failwithf "Not a record type" | ||||||
|  |  | ||||||
| open Myriad.Core |  | ||||||
|  |  | ||||||
| /// Myriad generator that stamps out a record with option types stripped | /// Myriad generator that stamps out a record with option types stripped | ||||||
| /// from the fields at the top level. | /// from the fields at the top level. | ||||||
| [<MyriadGenerator("remove-options")>] | [<MyriadGenerator("remove-options")>] | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								WoofWare.Myriad.Plugins/SynAttribute.fs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								WoofWare.Myriad.Plugins/SynAttribute.fs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | namespace WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
|  | open Fantomas.FCS.Syntax | ||||||
|  | open Fantomas.FCS.Text.Range | ||||||
|  | open Myriad.Core | ||||||
|  |  | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
|  | module internal SynAttribute = | ||||||
|  |     let internal compilationRepresentation : SynAttribute = | ||||||
|  |         { | ||||||
|  |             TypeName = SynLongIdent.CreateString "CompilationRepresentation" | ||||||
|  |             ArgExpr = | ||||||
|  |                 SynExpr.CreateLongIdent ( | ||||||
|  |                     false, | ||||||
|  |                     SynLongIdent.Create [ "CompilationRepresentationFlags" ; "ModuleSuffix" ], | ||||||
|  |                     None | ||||||
|  |                 ) | ||||||
|  |                 |> SynExpr.CreateParen | ||||||
|  |             Target = None | ||||||
|  |             AppliesToGetterAndSetter = false | ||||||
|  |             Range = range0 | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     let internal autoOpen : SynAttribute = | ||||||
|  |         { | ||||||
|  |             TypeName = SynLongIdent.CreateString "AutoOpen" | ||||||
|  |             ArgExpr = SynExpr.CreateConst SynConst.Unit | ||||||
|  |             Target = None | ||||||
|  |             AppliesToGetterAndSetter = false | ||||||
|  |             Range = range0 | ||||||
|  |         } | ||||||
							
								
								
									
										313
									
								
								WoofWare.Myriad.Plugins/SynExpr.fs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								WoofWare.Myriad.Plugins/SynExpr.fs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,313 @@ | |||||||
|  | namespace WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
|  | open Fantomas.FCS.Syntax | ||||||
|  | open Fantomas.FCS.SyntaxTrivia | ||||||
|  | open Myriad.Core | ||||||
|  | open Myriad.Core.Ast | ||||||
|  | open Fantomas.FCS.Text.Range | ||||||
|  |  | ||||||
|  | type internal CompExprBinding = | ||||||
|  |     | LetBang of varName : string * rhs : SynExpr | ||||||
|  |     | Let of varName : string * rhs : SynExpr | ||||||
|  |     | Use of varName : string * rhs : SynExpr | ||||||
|  |     | Do of body : SynExpr | ||||||
|  |  | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
|  | module internal SynExpr = | ||||||
|  |  | ||||||
|  |     /// {expr} |> {func} | ||||||
|  |     let pipeThroughFunction (func : SynExpr) (expr : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.CreateAppInfix ( | ||||||
|  |                 SynExpr.CreateLongIdent ( | ||||||
|  |                     SynLongIdent.SynLongIdent ( | ||||||
|  |                         [ Ident.Create "op_PipeRight" ], | ||||||
|  |                         [], | ||||||
|  |                         [ Some (IdentTrivia.OriginalNotation "|>") ] | ||||||
|  |                     ) | ||||||
|  |                 ), | ||||||
|  |                 expr | ||||||
|  |             ), | ||||||
|  |             func | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     /// if {cond} then {trueBranch} else {falseBranch} | ||||||
|  |     /// Note that this function puts the trueBranch last, for pipelining convenience: | ||||||
|  |     /// we assume that the `else` branch is more like an error case and is less interesting. | ||||||
|  |     let ifThenElse (cond : SynExpr) (falseBranch : SynExpr) (trueBranch : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.IfThenElse ( | ||||||
|  |             cond, | ||||||
|  |             trueBranch, | ||||||
|  |             Some falseBranch, | ||||||
|  |             DebugPointAtBinding.Yes range0, | ||||||
|  |             false, | ||||||
|  |             range0, | ||||||
|  |             { | ||||||
|  |                 IfKeyword = range0 | ||||||
|  |                 IsElif = false | ||||||
|  |                 ThenKeyword = range0 | ||||||
|  |                 ElseKeyword = Some range0 | ||||||
|  |                 IfToThenRange = range0 | ||||||
|  |             } | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     /// try {body} with | {exc} as exc -> {handler} | ||||||
|  |     let pipeThroughTryWith (exc : SynPat) (handler : SynExpr) (body : SynExpr) : SynExpr = | ||||||
|  |         let clause = | ||||||
|  |             SynMatchClause.Create (SynPat.As (exc, SynPat.CreateNamed (Ident.Create "exc"), range0), None, handler) | ||||||
|  |  | ||||||
|  |         SynExpr.TryWith ( | ||||||
|  |             body, | ||||||
|  |             [ clause ], | ||||||
|  |             range0, | ||||||
|  |             DebugPointAtTry.Yes range0, | ||||||
|  |             DebugPointAtWith.Yes range0, | ||||||
|  |             { | ||||||
|  |                 TryKeyword = range0 | ||||||
|  |                 TryToWithRange = range0 | ||||||
|  |                 WithKeyword = range0 | ||||||
|  |                 WithToEndRange = range0 | ||||||
|  |             } | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     /// {a} = {b} | ||||||
|  |     let equals (a : SynExpr) (b : SynExpr) = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.CreateAppInfix ( | ||||||
|  |                 SynExpr.CreateLongIdent ( | ||||||
|  |                     SynLongIdent.SynLongIdent ( | ||||||
|  |                         Ident.CreateLong "op_Equality", | ||||||
|  |                         [], | ||||||
|  |                         [ Some (IdentTrivia.OriginalNotation "=") ] | ||||||
|  |                     ) | ||||||
|  |                 ), | ||||||
|  |                 a | ||||||
|  |             ), | ||||||
|  |             b | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     /// {a} + {b} | ||||||
|  |     let plus (a : SynExpr) (b : SynExpr) = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.CreateAppInfix ( | ||||||
|  |                 SynExpr.CreateLongIdent ( | ||||||
|  |                     SynLongIdent.SynLongIdent ( | ||||||
|  |                         Ident.CreateLong "op_Addition", | ||||||
|  |                         [], | ||||||
|  |                         [ Some (IdentTrivia.OriginalNotation "+") ] | ||||||
|  |                     ) | ||||||
|  |                 ), | ||||||
|  |                 a | ||||||
|  |             ), | ||||||
|  |             b | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     let rec stripOptionalParen (expr : SynExpr) : SynExpr = | ||||||
|  |         match expr with | ||||||
|  |         | SynExpr.Paren (expr, _, _, _) -> stripOptionalParen expr | ||||||
|  |         | expr -> expr | ||||||
|  |  | ||||||
|  |     /// Given e.g. "byte", returns "System.Byte". | ||||||
|  |     let qualifyPrimitiveType (typeName : string) : LongIdent = | ||||||
|  |         match typeName with | ||||||
|  |         | "float32" -> [ "System" ; "Single" ] | ||||||
|  |         | "float" -> [ "System" ; "Double" ] | ||||||
|  |         | "byte" | ||||||
|  |         | "uint8" -> [ "System" ; "Byte" ] | ||||||
|  |         | "sbyte" -> [ "System" ; "SByte" ] | ||||||
|  |         | "int16" -> [ "System" ; "Int16" ] | ||||||
|  |         | "int" -> [ "System" ; "Int32" ] | ||||||
|  |         | "int64" -> [ "System" ; "Int64" ] | ||||||
|  |         | "uint16" -> [ "System" ; "UInt16" ] | ||||||
|  |         | "uint" | ||||||
|  |         | "uint32" -> [ "System" ; "UInt32" ] | ||||||
|  |         | "uint64" -> [ "System" ; "UInt64" ] | ||||||
|  |         | _ -> failwith $"Unable to identify a parsing function `string -> %s{typeName}`" | ||||||
|  |         |> List.map Ident.Create | ||||||
|  |  | ||||||
|  |     /// {obj}.{meth} {arg} | ||||||
|  |     let callMethodArg (meth : string) (arg : SynExpr) (obj : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.DotGet ( | ||||||
|  |                 obj, | ||||||
|  |                 range0, | ||||||
|  |                 SynLongIdent.SynLongIdent (id = [ Ident.Create meth ], dotRanges = [], trivia = [ None ]), | ||||||
|  |                 range0 | ||||||
|  |             ), | ||||||
|  |             arg | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     /// {obj}.{meth}() | ||||||
|  |     let callMethod (meth : string) (obj : SynExpr) : SynExpr = | ||||||
|  |         callMethodArg meth (SynExpr.CreateConst SynConst.Unit) obj | ||||||
|  |  | ||||||
|  |     /// {obj}.{meth}<ty>() | ||||||
|  |     let callGenericMethod (meth : string) (ty : string) (obj : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.TypeApp ( | ||||||
|  |                 SynExpr.DotGet (obj, range0, SynLongIdent.Create [ meth ], range0), | ||||||
|  |                 range0, | ||||||
|  |                 [ SynType.CreateLongIdent ty ], | ||||||
|  |                 [], | ||||||
|  |                 Some range0, | ||||||
|  |                 range0, | ||||||
|  |                 range0 | ||||||
|  |             ), | ||||||
|  |             SynExpr.CreateConst SynConst.Unit | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     let index (property : SynExpr) (obj : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.DotIndexedGet (obj, property, range0, range0) | ||||||
|  |  | ||||||
|  |     /// (fun {varName} -> {body}) | ||||||
|  |     let createLambda (varName : string) (body : SynExpr) : SynExpr = | ||||||
|  |         let parsedDataPat = [ SynPat.CreateNamed (Ident.Create varName) ] | ||||||
|  |  | ||||||
|  |         SynExpr.Lambda ( | ||||||
|  |             false, | ||||||
|  |             false, | ||||||
|  |             SynSimplePats.Create [ SynSimplePat.CreateId (Ident.Create varName) ], | ||||||
|  |             body, | ||||||
|  |             Some (parsedDataPat, body), | ||||||
|  |             range0, | ||||||
|  |             { | ||||||
|  |                 ArrowRange = Some range0 | ||||||
|  |             } | ||||||
|  |         ) | ||||||
|  |         |> SynExpr.CreateParen | ||||||
|  |  | ||||||
|  |     let reraise : SynExpr = | ||||||
|  |         SynExpr.CreateApp (SynExpr.CreateIdent (Ident.Create "reraise"), SynExpr.CreateConst SynConst.Unit) | ||||||
|  |  | ||||||
|  |     /// {body} |> fun a -> Async.StartAsTask (a, ?cancellationToken=ct) | ||||||
|  |     let startAsTask (ct : SynLongIdent) (body : SynExpr) = | ||||||
|  |         let lambda = | ||||||
|  |             SynExpr.CreateApp ( | ||||||
|  |                 SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "StartAsTask" ]), | ||||||
|  |                 SynExpr.CreateParenedTuple | ||||||
|  |                     [ | ||||||
|  |                         SynExpr.CreateLongIdent (SynLongIdent.CreateString "a") | ||||||
|  |                         equals | ||||||
|  |                             (SynExpr.LongIdent (true, SynLongIdent.CreateString "cancellationToken", None, range0)) | ||||||
|  |                             (SynExpr.CreateLongIdent ct) | ||||||
|  |                     ] | ||||||
|  |             ) | ||||||
|  |             |> createLambda "a" | ||||||
|  |  | ||||||
|  |         pipeThroughFunction lambda body | ||||||
|  |  | ||||||
|  |     /// {compExpr} { {lets} ; return {ret} } | ||||||
|  |     let createCompExpr (compExpr : string) (retBody : SynExpr) (lets : CompExprBinding list) : SynExpr = | ||||||
|  |         let retStatement = SynExpr.YieldOrReturn ((false, true), retBody, range0) | ||||||
|  |  | ||||||
|  |         let contents : SynExpr = | ||||||
|  |             (retStatement, List.rev lets) | ||||||
|  |             ||> List.fold (fun state binding -> | ||||||
|  |                 match binding with | ||||||
|  |                 | LetBang (lhs, rhs) -> | ||||||
|  |                     SynExpr.LetOrUseBang ( | ||||||
|  |                         DebugPointAtBinding.Yes range0, | ||||||
|  |                         false, | ||||||
|  |                         true, | ||||||
|  |                         SynPat.CreateNamed (Ident.Create lhs), | ||||||
|  |                         rhs, | ||||||
|  |                         [], | ||||||
|  |                         state, | ||||||
|  |                         range0, | ||||||
|  |                         { | ||||||
|  |                             EqualsRange = Some range0 | ||||||
|  |                         } | ||||||
|  |                     ) | ||||||
|  |                 | Let (lhs, rhs) -> | ||||||
|  |                     SynExpr.LetOrUse ( | ||||||
|  |                         false, | ||||||
|  |                         false, | ||||||
|  |                         [ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ], | ||||||
|  |                         state, | ||||||
|  |                         range0, | ||||||
|  |                         { | ||||||
|  |                             SynExprLetOrUseTrivia.InKeyword = None | ||||||
|  |                         } | ||||||
|  |                     ) | ||||||
|  |                 | Use (lhs, rhs) -> | ||||||
|  |                     SynExpr.LetOrUse ( | ||||||
|  |                         false, | ||||||
|  |                         true, | ||||||
|  |                         [ SynBinding.Let (pattern = SynPat.CreateNamed (Ident.Create lhs), expr = rhs) ], | ||||||
|  |                         state, | ||||||
|  |                         range0, | ||||||
|  |                         { | ||||||
|  |                             SynExprLetOrUseTrivia.InKeyword = None | ||||||
|  |                         } | ||||||
|  |                     ) | ||||||
|  |                 | Do body -> SynExpr.CreateSequential [ SynExpr.Do (body, range0) ; state ] | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.CreateIdent (Ident.Create compExpr), | ||||||
|  |             SynExpr.ComputationExpr (false, contents, range0) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     /// {expr} |> Async.AwaitTask | ||||||
|  |     let awaitTask (expr : SynExpr) : SynExpr = | ||||||
|  |         expr | ||||||
|  |         |> pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "AwaitTask" ])) | ||||||
|  |  | ||||||
|  |     /// {ident}.ToString () | ||||||
|  |     /// with special casing for some types like DateTime | ||||||
|  |     let toString (ty : SynType) (ident : SynExpr) = | ||||||
|  |         match ty with | ||||||
|  |         | DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-dd") | ||||||
|  |         | DateTime -> | ||||||
|  |             ident | ||||||
|  |             |> callMethodArg "ToString" (SynExpr.CreateConstString "yyyy-MM-ddTHH:mm:ss") | ||||||
|  |         | _ -> callMethod "ToString" ident | ||||||
|  |  | ||||||
|  |     let upcast' (ty : SynType) (e : SynExpr) = SynExpr.Upcast (e, ty, range0) | ||||||
|  |  | ||||||
|  |     let synBindingTriviaZero (isMember : bool) = | ||||||
|  |         { | ||||||
|  |             SynBindingTrivia.EqualsRange = Some range0 | ||||||
|  |             InlineKeyword = None | ||||||
|  |             LeadingKeyword = | ||||||
|  |                 if isMember then | ||||||
|  |                     SynLeadingKeyword.Member range0 | ||||||
|  |                 else | ||||||
|  |                     SynLeadingKeyword.Let range0 | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     /// {ident} - {rhs} | ||||||
|  |     let minus (ident : SynLongIdent) (rhs : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.CreateAppInfix ( | ||||||
|  |                 SynExpr.CreateLongIdent ( | ||||||
|  |                     SynLongIdent.SynLongIdent ( | ||||||
|  |                         [ Ident.Create "op_Subtraction" ], | ||||||
|  |                         [], | ||||||
|  |                         [ Some (IdentTrivia.OriginalNotation "-") ] | ||||||
|  |                     ) | ||||||
|  |                 ), | ||||||
|  |                 SynExpr.CreateLongIdent ident | ||||||
|  |             ), | ||||||
|  |             rhs | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     /// {ident} - {n} | ||||||
|  |     let minusN (ident : SynLongIdent) (n : int) : SynExpr = | ||||||
|  |         minus ident (SynExpr.CreateConst (SynConst.Int32 n)) | ||||||
|  |  | ||||||
|  |     /// {y} > {x} | ||||||
|  |     let greaterThan (x : SynExpr) (y : SynExpr) : SynExpr = | ||||||
|  |         SynExpr.CreateApp ( | ||||||
|  |             SynExpr.CreateAppInfix ( | ||||||
|  |                 SynExpr.CreateLongIdent ( | ||||||
|  |                     SynLongIdent.SynLongIdent ( | ||||||
|  |                         [ Ident.Create "op_GreaterThan" ], | ||||||
|  |                         [], | ||||||
|  |                         [ Some (IdentTrivia.OriginalNotation ">") ] | ||||||
|  |                     ) | ||||||
|  |                 ), | ||||||
|  |                 y | ||||||
|  |             ), | ||||||
|  |             x | ||||||
|  |         ) | ||||||
| @@ -1,49 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
|  |  | ||||||
| type internal CompExprBinding = |  | ||||||
|     | LetBang of varName : string * rhs : SynExpr |  | ||||||
|     | Let of varName : string * rhs : SynExpr |  | ||||||
|     | Use of varName : string * rhs : SynExpr |  | ||||||
|     | Do of body : SynExpr |  | ||||||
|  |  | ||||||
| (* |  | ||||||
| Potential API! |  | ||||||
| type internal CompExprBindings = |  | ||||||
|     private |  | ||||||
|         { |  | ||||||
|             /// These are stored in reverse. |  | ||||||
|             Bindings : CompExprBinding list |  | ||||||
|             CompExprName : string |  | ||||||
|         } |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal CompExprBindings = |  | ||||||
|     let make (name : string) : CompExprBindings = |  | ||||||
|         { |  | ||||||
|             Bindings = [] |  | ||||||
|             CompExprName = name |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let thenDo (body : SynExpr) (bindings : CompExprBindings) = |  | ||||||
|         { bindings with |  | ||||||
|             Bindings = (Do body :: bindings.Bindings) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let thenLet (varName : string) (value : SynExpr) (bindings : CompExprBindings) = |  | ||||||
|         { bindings with |  | ||||||
|             Bindings = (Let (varName, value) :: bindings.Bindings) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let thenLetBang (varName : string) (value : SynExpr) (bindings : CompExprBindings) = |  | ||||||
|         { bindings with |  | ||||||
|             Bindings = (LetBang (varName, value) :: bindings.Bindings) |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     let thenUse (varName : string) (value : SynExpr) (bindings : CompExprBindings) = |  | ||||||
|         { bindings with |  | ||||||
|             Bindings = (LetBang (varName, value) :: bindings.Bindings) |  | ||||||
|         } |  | ||||||
| *) |  | ||||||
| @@ -1,9 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Xml |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal PreXmlDoc = |  | ||||||
|     let create (s : string) : PreXmlDoc = |  | ||||||
|         PreXmlDoc.Create ([| " " + s |], range0) |  | ||||||
| @@ -1,16 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynArgPats = |  | ||||||
|     let create (caseNames : Ident list) : SynArgPats = |  | ||||||
|         match caseNames.Length with |  | ||||||
|         | 0 -> SynArgPats.Pats [] |  | ||||||
|         | 1 -> [ SynPat.named caseNames.[0].idText ] |> SynArgPats.Pats |  | ||||||
|         | _ -> |  | ||||||
|             caseNames |  | ||||||
|             |> List.map (fun i -> SynPat.named i.idText) |  | ||||||
|             |> SynPat.tuple |  | ||||||
|             |> List.singleton |  | ||||||
|             |> SynArgPats.Pats |  | ||||||
| @@ -1,36 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynAttribute = |  | ||||||
|     let internal compilationRepresentation : SynAttribute = |  | ||||||
|         { |  | ||||||
|             TypeName = SynLongIdent.createS "CompilationRepresentation" |  | ||||||
|             ArgExpr = |  | ||||||
|                 [ "CompilationRepresentationFlags" ; "ModuleSuffix" ] |  | ||||||
|                 |> SynExpr.createLongIdent |  | ||||||
|                 |> SynExpr.paren |  | ||||||
|             Target = None |  | ||||||
|             AppliesToGetterAndSetter = false |  | ||||||
|             Range = range0 |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let internal requireQualifiedAccess : SynAttribute = |  | ||||||
|         { |  | ||||||
|             TypeName = SynLongIdent.createS "RequireQualifiedAccess" |  | ||||||
|             ArgExpr = SynExpr.CreateConst () |  | ||||||
|             Target = None |  | ||||||
|             AppliesToGetterAndSetter = false |  | ||||||
|             Range = range0 |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let internal autoOpen : SynAttribute = |  | ||||||
|         { |  | ||||||
|             TypeName = SynLongIdent.createS "AutoOpen" |  | ||||||
|             ArgExpr = SynExpr.CreateConst () |  | ||||||
|             Target = None |  | ||||||
|             AppliesToGetterAndSetter = false |  | ||||||
|             Range = range0 |  | ||||||
|         } |  | ||||||
| @@ -1,204 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Fantomas.FCS.Xml |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynBinding = |  | ||||||
|  |  | ||||||
|     let rec private stripParen (pat : SynPat) = |  | ||||||
|         match pat with |  | ||||||
|         | SynPat.Paren (p, _) -> stripParen p |  | ||||||
|         | _ -> pat |  | ||||||
|  |  | ||||||
|     let rec private getName (pat : SynPat) : Ident option = |  | ||||||
|         match stripParen pat with |  | ||||||
|         | SynPat.Named (SynIdent.SynIdent (name, _), _, _, _) -> Some name |  | ||||||
|         | SynPat.Typed (pat, _, _) -> getName pat |  | ||||||
|         | SynPat.LongIdent (SynLongIdent.SynLongIdent (longIdent, _, _), _, _, _, _, _) -> |  | ||||||
|             match longIdent with |  | ||||||
|             | [ x ] -> Some x |  | ||||||
|             | _ -> failwithf "got long ident %O ; can only get the name of a long ident with one component" longIdent |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let private getArgInfo (pat : SynPat) : SynArgInfo list = |  | ||||||
|         // TODO: this only copes with one layer of tupling |  | ||||||
|         match stripParen pat with |  | ||||||
|         | SynPat.Tuple (_, pats, _, _) -> pats |> List.map (fun pat -> SynArgInfo.SynArgInfo ([], false, getName pat)) |  | ||||||
|         | pat -> [ SynArgInfo.SynArgInfo (SynAttributes.Empty, false, getName pat) ] |  | ||||||
|  |  | ||||||
|     let triviaZero (isMember : bool) = |  | ||||||
|         { |  | ||||||
|             SynBindingTrivia.EqualsRange = Some range0 |  | ||||||
|             InlineKeyword = None |  | ||||||
|             LeadingKeyword = |  | ||||||
|                 if isMember then |  | ||||||
|                     SynLeadingKeyword.Member range0 |  | ||||||
|                 else |  | ||||||
|                     SynLeadingKeyword.Let range0 |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let basic (name : LongIdent) (args : SynPat list) (body : SynExpr) : SynBinding = |  | ||||||
|         let valInfo : SynValInfo = |  | ||||||
|             args |  | ||||||
|             |> List.map getArgInfo |  | ||||||
|             |> fun x -> SynValInfo.SynValInfo (x, SynArgInfo.SynArgInfo ([], false, None)) |  | ||||||
|  |  | ||||||
|         SynBinding.SynBinding ( |  | ||||||
|             None, |  | ||||||
|             SynBindingKind.Normal, |  | ||||||
|             false, |  | ||||||
|             false, |  | ||||||
|             [], |  | ||||||
|             PreXmlDoc.Empty, |  | ||||||
|             SynValData.SynValData (None, valInfo, None), |  | ||||||
|             SynPat.identWithArgs name (SynArgPats.Pats args), |  | ||||||
|             None, |  | ||||||
|             body, |  | ||||||
|             range0, |  | ||||||
|             DebugPointAtBinding.Yes range0, |  | ||||||
|             triviaZero false |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let withAccessibility (acc : SynAccess option) (binding : SynBinding) : SynBinding = |  | ||||||
|         match binding with |  | ||||||
|         | SynBinding (_, kind, inl, mut, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia) -> |  | ||||||
|             let headPat = |  | ||||||
|                 match headPat with |  | ||||||
|                 | SynPat.LongIdent (ident, extra, options, argPats, _, range) -> |  | ||||||
|                     SynPat.LongIdent (ident, extra, options, argPats, acc, range) |  | ||||||
|                 | _ -> failwithf "unrecognised head pattern: %O" headPat |  | ||||||
|  |  | ||||||
|             SynBinding (acc, kind, inl, mut, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia) |  | ||||||
|  |  | ||||||
|     let withXmlDoc (doc : PreXmlDoc) (binding : SynBinding) : SynBinding = |  | ||||||
|         match binding with |  | ||||||
|         | SynBinding (acc, kind, inl, mut, attrs, _, valData, headPat, returnInfo, expr, range, debugPoint, trivia) -> |  | ||||||
|             SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, returnInfo, expr, range, debugPoint, trivia) |  | ||||||
|  |  | ||||||
|     let withReturnAnnotation (ty : SynType) (binding : SynBinding) : SynBinding = |  | ||||||
|         match binding with |  | ||||||
|         | SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, _, expr, range, debugPoint, trivia) -> |  | ||||||
|             let retInfo = |  | ||||||
|                 SynBindingReturnInfo.SynBindingReturnInfo ( |  | ||||||
|                     ty, |  | ||||||
|                     range0, |  | ||||||
|                     [], |  | ||||||
|                     { |  | ||||||
|                         ColonRange = Some range0 |  | ||||||
|                     } |  | ||||||
|                 ) |  | ||||||
|  |  | ||||||
|             SynBinding ( |  | ||||||
|                 acc, |  | ||||||
|                 kind, |  | ||||||
|                 inl, |  | ||||||
|                 mut, |  | ||||||
|                 attrs, |  | ||||||
|                 doc, |  | ||||||
|                 valData, |  | ||||||
|                 headPat, |  | ||||||
|                 Some retInfo, |  | ||||||
|                 expr, |  | ||||||
|                 range, |  | ||||||
|                 debugPoint, |  | ||||||
|                 trivia |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|     let inline makeInline (binding : SynBinding) : SynBinding = |  | ||||||
|         match binding with |  | ||||||
|         | SynBinding (acc, kind, _, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) -> |  | ||||||
|             SynBinding ( |  | ||||||
|                 acc, |  | ||||||
|                 kind, |  | ||||||
|                 true, |  | ||||||
|                 mut, |  | ||||||
|                 attrs, |  | ||||||
|                 doc, |  | ||||||
|                 valData, |  | ||||||
|                 headPat, |  | ||||||
|                 ret, |  | ||||||
|                 expr, |  | ||||||
|                 range, |  | ||||||
|                 debugPoint, |  | ||||||
|                 { trivia with |  | ||||||
|                     InlineKeyword = Some range0 |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|     let inline makeNotInline (binding : SynBinding) : SynBinding = |  | ||||||
|         match binding with |  | ||||||
|         | SynBinding (acc, kind, _, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) -> |  | ||||||
|             SynBinding ( |  | ||||||
|                 acc, |  | ||||||
|                 kind, |  | ||||||
|                 false, |  | ||||||
|                 mut, |  | ||||||
|                 attrs, |  | ||||||
|                 doc, |  | ||||||
|                 valData, |  | ||||||
|                 headPat, |  | ||||||
|                 ret, |  | ||||||
|                 expr, |  | ||||||
|                 range, |  | ||||||
|                 debugPoint, |  | ||||||
|                 { trivia with |  | ||||||
|                     InlineKeyword = None |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|     let inline setInline (isInline : bool) (binding : SynBinding) : SynBinding = |  | ||||||
|         if isInline then |  | ||||||
|             makeInline binding |  | ||||||
|         else |  | ||||||
|             makeNotInline binding |  | ||||||
|  |  | ||||||
|     let makeStaticMember (binding : SynBinding) : SynBinding = |  | ||||||
|         let memberFlags = |  | ||||||
|             { |  | ||||||
|                 SynMemberFlags.IsInstance = false |  | ||||||
|                 SynMemberFlags.IsDispatchSlot = false |  | ||||||
|                 SynMemberFlags.IsOverrideOrExplicitImpl = false |  | ||||||
|                 SynMemberFlags.IsFinal = false |  | ||||||
|                 SynMemberFlags.GetterOrSetterIsCompilerGenerated = false |  | ||||||
|                 SynMemberFlags.MemberKind = SynMemberKind.Member |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         match binding with |  | ||||||
|         | SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) -> |  | ||||||
|             let valData = |  | ||||||
|                 match valData with |  | ||||||
|                 | SynValData.SynValData (_, valInfo, _) -> SynValData.SynValData (Some memberFlags, valInfo, None) |  | ||||||
|  |  | ||||||
|             let trivia = |  | ||||||
|                 { trivia with |  | ||||||
|                     LeadingKeyword = SynLeadingKeyword.StaticMember (range0, range0) |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) |  | ||||||
|  |  | ||||||
|     let makeInstanceMember (binding : SynBinding) : SynBinding = |  | ||||||
|         let memberFlags = |  | ||||||
|             { |  | ||||||
|                 SynMemberFlags.IsInstance = true |  | ||||||
|                 SynMemberFlags.IsDispatchSlot = false |  | ||||||
|                 SynMemberFlags.IsOverrideOrExplicitImpl = true |  | ||||||
|                 SynMemberFlags.IsFinal = false |  | ||||||
|                 SynMemberFlags.GetterOrSetterIsCompilerGenerated = false |  | ||||||
|                 SynMemberFlags.MemberKind = SynMemberKind.Member |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         match binding with |  | ||||||
|         | SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) -> |  | ||||||
|             let valData = |  | ||||||
|                 match valData with |  | ||||||
|                 | SynValData.SynValData (_, valInfo, _) -> SynValData.SynValData (Some memberFlags, valInfo, None) |  | ||||||
|  |  | ||||||
|             let trivia = |  | ||||||
|                 { trivia with |  | ||||||
|                     LeadingKeyword = SynLeadingKeyword.Member range0 |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             SynBinding (acc, kind, inl, mut, attrs, doc, valData, headPat, ret, expr, range, debugPoint, trivia) |  | ||||||
| @@ -1,50 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.Xml |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynComponentInfo = |  | ||||||
|     let inline createLong (name : LongIdent) = |  | ||||||
|         SynComponentInfo.SynComponentInfo ([], None, [], name, PreXmlDoc.Empty, false, None, range0) |  | ||||||
|  |  | ||||||
|     let inline create (name : Ident) = createLong [ name ] |  | ||||||
|  |  | ||||||
|     let inline withDocString (doc : PreXmlDoc) (i : SynComponentInfo) : SynComponentInfo = |  | ||||||
|         match i with |  | ||||||
|         | SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, _, postfix, access, range) -> |  | ||||||
|             SynComponentInfo (attrs, typars, constraints, name, doc, postfix, access, range) |  | ||||||
|  |  | ||||||
|     let inline setGenerics (typars : SynTyparDecls option) (i : SynComponentInfo) : SynComponentInfo = |  | ||||||
|         match i with |  | ||||||
|         | SynComponentInfo.SynComponentInfo (attrs, _, constraints, name, doc, postfix, access, range) -> |  | ||||||
|             SynComponentInfo (attrs, typars, constraints, name, doc, postfix, access, range) |  | ||||||
|  |  | ||||||
|     let inline withGenerics (typars : SynTyparDecl list) (i : SynComponentInfo) : SynComponentInfo = |  | ||||||
|         let inner = |  | ||||||
|             if typars.IsEmpty then |  | ||||||
|                 None |  | ||||||
|             else |  | ||||||
|                 Some (SynTyparDecls.PostfixList (typars, [], range0)) |  | ||||||
|  |  | ||||||
|         setGenerics inner i |  | ||||||
|  |  | ||||||
|     let inline setAccessibility (acc : SynAccess option) (i : SynComponentInfo) : SynComponentInfo = |  | ||||||
|         match i with |  | ||||||
|         | SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, doc, postfix, _, range) -> |  | ||||||
|             SynComponentInfo.SynComponentInfo (attrs, typars, constraints, name, doc, postfix, acc, range) |  | ||||||
|  |  | ||||||
|     let inline withAccessibility (acc : SynAccess) (i : SynComponentInfo) : SynComponentInfo = |  | ||||||
|         setAccessibility (Some acc) i |  | ||||||
|  |  | ||||||
|     let inline addAttributes (attrs : SynAttribute list) (i : SynComponentInfo) : SynComponentInfo = |  | ||||||
|         match i with |  | ||||||
|         | SynComponentInfo.SynComponentInfo (oldAttrs, typars, constraints, name, doc, postfix, acc, range) -> |  | ||||||
|             let attrs = |  | ||||||
|                 { |  | ||||||
|                     SynAttributeList.Attributes = attrs |  | ||||||
|                     SynAttributeList.Range = range0 |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             SynComponentInfo.SynComponentInfo ((attrs :: oldAttrs), typars, constraints, name, doc, postfix, acc, range) |  | ||||||
| @@ -1,300 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Myriad.Core |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<AutoOpen>] |  | ||||||
| module internal SynExprExtensions = |  | ||||||
|     type SynExpr with |  | ||||||
|         static member CreateConst (s : string) : SynExpr = |  | ||||||
|             SynExpr.Const (SynConst.String (s, SynStringKind.Regular, range0), range0) |  | ||||||
|  |  | ||||||
|         static member CreateConst () : SynExpr = SynExpr.Const (SynConst.Unit, range0) |  | ||||||
|  |  | ||||||
|         static member CreateConst (i : int32) : SynExpr = |  | ||||||
|             SynExpr.Const (SynConst.Int32 i, range0) |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynExpr = |  | ||||||
|  |  | ||||||
|     /// {f} {x} |  | ||||||
|     let applyFunction (f : SynExpr) (x : SynExpr) : SynExpr = SynExpr.CreateApp (f, x) |  | ||||||
|  |  | ||||||
|     /// {f} {x} |  | ||||||
|     let inline applyTo (x : SynExpr) (f : SynExpr) : SynExpr = applyFunction f x |  | ||||||
|  |  | ||||||
|     /// {expr} |> {func} |  | ||||||
|     let pipeThroughFunction (func : SynExpr) (expr : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.pipe, expr) |  | ||||||
|         |> applyTo func |  | ||||||
|  |  | ||||||
|     /// if {cond} then {trueBranch} else {falseBranch} |  | ||||||
|     /// Note that this function puts the trueBranch last, for pipelining convenience: |  | ||||||
|     /// we assume that the `else` branch is more like an error case and is less interesting. |  | ||||||
|     let ifThenElse (cond : SynExpr) (falseBranch : SynExpr) (trueBranch : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.IfThenElse ( |  | ||||||
|             cond, |  | ||||||
|             trueBranch, |  | ||||||
|             Some falseBranch, |  | ||||||
|             DebugPointAtBinding.Yes range0, |  | ||||||
|             false, |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 IfKeyword = range0 |  | ||||||
|                 IsElif = false |  | ||||||
|                 ThenKeyword = range0 |  | ||||||
|                 ElseKeyword = Some range0 |  | ||||||
|                 IfToThenRange = range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     /// try {body} with | {exc} as exc -> {handler} |  | ||||||
|     let pipeThroughTryWith (exc : SynPat) (handler : SynExpr) (body : SynExpr) : SynExpr = |  | ||||||
|         let clause = |  | ||||||
|             SynMatchClause.create (SynPat.As (exc, SynPat.named "exc", range0)) handler |  | ||||||
|  |  | ||||||
|         SynExpr.TryWith ( |  | ||||||
|             body, |  | ||||||
|             [ clause ], |  | ||||||
|             range0, |  | ||||||
|             DebugPointAtTry.Yes range0, |  | ||||||
|             DebugPointAtWith.Yes range0, |  | ||||||
|             { |  | ||||||
|                 TryKeyword = range0 |  | ||||||
|                 TryToWithRange = range0 |  | ||||||
|                 WithKeyword = range0 |  | ||||||
|                 WithToEndRange = range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     /// {a} = {b} |  | ||||||
|     let equals (a : SynExpr) (b : SynExpr) = |  | ||||||
|         SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.eq, a) |> applyTo b |  | ||||||
|  |  | ||||||
|     /// {a} + {b} |  | ||||||
|     let plus (a : SynExpr) (b : SynExpr) = |  | ||||||
|         SynExpr.CreateAppInfix ( |  | ||||||
|             SynExpr.CreateLongIdent ( |  | ||||||
|                 SynLongIdent.SynLongIdent ( |  | ||||||
|                     Ident.CreateLong "op_Addition", |  | ||||||
|                     [], |  | ||||||
|                     [ Some (IdentTrivia.OriginalNotation "+") ] |  | ||||||
|                 ) |  | ||||||
|             ), |  | ||||||
|             a |  | ||||||
|         ) |  | ||||||
|         |> applyTo b |  | ||||||
|  |  | ||||||
|     let rec stripOptionalParen (expr : SynExpr) : SynExpr = |  | ||||||
|         match expr with |  | ||||||
|         | SynExpr.Paren (expr, _, _, _) -> stripOptionalParen expr |  | ||||||
|         | expr -> expr |  | ||||||
|  |  | ||||||
|     /// {obj}.{meth} {arg} |  | ||||||
|     let callMethodArg (meth : string) (arg : SynExpr) (obj : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.DotGet ( |  | ||||||
|             obj, |  | ||||||
|             range0, |  | ||||||
|             SynLongIdent.SynLongIdent (id = [ Ident.create meth ], dotRanges = [], trivia = [ None ]), |  | ||||||
|             range0 |  | ||||||
|         ) |  | ||||||
|         |> applyTo arg |  | ||||||
|  |  | ||||||
|     /// {obj}.{meth}() |  | ||||||
|     let callMethod (meth : string) (obj : SynExpr) : SynExpr = |  | ||||||
|         callMethodArg meth (SynExpr.CreateConst ()) obj |  | ||||||
|  |  | ||||||
|     let callGenericMethod (meth : string) (ty : LongIdent) (obj : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.TypeApp ( |  | ||||||
|             SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0), |  | ||||||
|             range0, |  | ||||||
|             [ SynType.LongIdent (SynLongIdent.create ty) ], |  | ||||||
|             [], |  | ||||||
|             Some range0, |  | ||||||
|             range0, |  | ||||||
|             range0 |  | ||||||
|         ) |  | ||||||
|         |> applyTo (SynExpr.CreateConst ()) |  | ||||||
|  |  | ||||||
|     /// {obj}.{meth}<ty>() |  | ||||||
|     let callGenericMethod' (meth : string) (ty : string) (obj : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.TypeApp ( |  | ||||||
|             SynExpr.DotGet (obj, range0, SynLongIdent.createS meth, range0), |  | ||||||
|             range0, |  | ||||||
|             [ SynType.createLongIdent' [ ty ] ], |  | ||||||
|             [], |  | ||||||
|             Some range0, |  | ||||||
|             range0, |  | ||||||
|             range0 |  | ||||||
|         ) |  | ||||||
|         |> applyTo (SynExpr.CreateConst ()) |  | ||||||
|  |  | ||||||
|     let inline index (property : SynExpr) (obj : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.DotIndexedGet (obj, property, range0, range0) |  | ||||||
|  |  | ||||||
|     let inline paren (e : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.Paren (e, range0, Some range0, range0) |  | ||||||
|  |  | ||||||
|     /// (fun {varName} -> {body}) |  | ||||||
|     let createLambda (varName : string) (body : SynExpr) : SynExpr = |  | ||||||
|         let parsedDataPat = [ SynPat.named varName ] |  | ||||||
|  |  | ||||||
|         SynExpr.Lambda ( |  | ||||||
|             false, |  | ||||||
|             false, |  | ||||||
|             SynSimplePats.Create [ SynSimplePat.CreateId (Ident.Create varName) ], |  | ||||||
|             body, |  | ||||||
|             Some (parsedDataPat, body), |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 ArrowRange = Some range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|         |> paren |  | ||||||
|  |  | ||||||
|     let createThunk (body : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.Lambda ( |  | ||||||
|             false, |  | ||||||
|             false, |  | ||||||
|             SynSimplePats.Create [], |  | ||||||
|             body, |  | ||||||
|             Some ([ SynPat.unit ], body), |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 ArrowRange = Some range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|         |> paren |  | ||||||
|  |  | ||||||
|     let inline createIdent (s : string) : SynExpr = SynExpr.Ident (Ident (s, range0)) |  | ||||||
|  |  | ||||||
|     let inline createIdent' (i : Ident) : SynExpr = SynExpr.Ident i |  | ||||||
|  |  | ||||||
|     let inline createLongIdent' (ident : Ident list) : SynExpr = |  | ||||||
|         SynExpr.LongIdent (false, SynLongIdent.create ident, None, range0) |  | ||||||
|  |  | ||||||
|     let inline createLongIdent (ident : string list) : SynExpr = |  | ||||||
|         createLongIdent' (ident |> List.map Ident.create) |  | ||||||
|  |  | ||||||
|     let tupleNoParen (args : SynExpr list) : SynExpr = |  | ||||||
|         SynExpr.Tuple (false, args, List.replicate (args.Length - 1) range0, range0) |  | ||||||
|  |  | ||||||
|     let inline tuple (args : SynExpr list) = args |> tupleNoParen |> paren |  | ||||||
|  |  | ||||||
|     /// {body} |> fun a -> Async.StartAsTask (a, ?cancellationToken=ct) |  | ||||||
|     let startAsTask (ct : Ident) (body : SynExpr) = |  | ||||||
|         let lambda = |  | ||||||
|             [ |  | ||||||
|                 createIdent "a" |  | ||||||
|                 equals |  | ||||||
|                     (SynExpr.LongIdent (true, SynLongIdent.createS "cancellationToken", None, range0)) |  | ||||||
|                     (createIdent' ct) |  | ||||||
|             ] |  | ||||||
|             |> tuple |  | ||||||
|             |> applyFunction (createLongIdent [ "Async" ; "StartAsTask" ]) |  | ||||||
|             |> createLambda "a" |  | ||||||
|  |  | ||||||
|         pipeThroughFunction lambda body |  | ||||||
|  |  | ||||||
|     let inline createLet (bindings : SynBinding list) (body : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.LetOrUse (false, false, bindings, body, range0, SynExprLetOrUseTrivia.empty) |  | ||||||
|  |  | ||||||
|     let inline createMatch (matchOn : SynExpr) (cases : SynMatchClause list) : SynExpr = |  | ||||||
|         SynExpr.Match ( |  | ||||||
|             DebugPointAtBinding.Yes range0, |  | ||||||
|             matchOn, |  | ||||||
|             cases, |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 MatchKeyword = range0 |  | ||||||
|                 WithKeyword = range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let typeAnnotate (ty : SynType) (expr : SynExpr) : SynExpr = SynExpr.Typed (expr, ty, range0) |  | ||||||
|  |  | ||||||
|     let inline createNew (ty : SynType) (args : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.New (false, ty, paren args, range0) |  | ||||||
|  |  | ||||||
|     let inline createWhile (cond : SynExpr) (body : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.While (DebugPointAtWhile.Yes range0, cond, body, range0) |  | ||||||
|  |  | ||||||
|     let inline createNull () : SynExpr = SynExpr.Null range0 |  | ||||||
|  |  | ||||||
|     let reraise : SynExpr = createIdent "reraise" |> applyTo (SynExpr.CreateConst ()) |  | ||||||
|  |  | ||||||
|     let sequential (exprs : SynExpr list) : SynExpr = |  | ||||||
|         exprs |  | ||||||
|         |> List.reduce (fun a b -> SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, false, a, b, range0)) |  | ||||||
|  |  | ||||||
|     /// {compExpr} { {lets} ; return {ret} } |  | ||||||
|     let createCompExpr (compExpr : string) (retBody : SynExpr) (lets : CompExprBinding list) : SynExpr = |  | ||||||
|         let retStatement = SynExpr.YieldOrReturn ((false, true), retBody, range0) |  | ||||||
|  |  | ||||||
|         let contents : SynExpr = |  | ||||||
|             (retStatement, List.rev lets) |  | ||||||
|             ||> List.fold (fun state binding -> |  | ||||||
|                 match binding with |  | ||||||
|                 | LetBang (lhs, rhs) -> |  | ||||||
|                     SynExpr.LetOrUseBang ( |  | ||||||
|                         DebugPointAtBinding.Yes range0, |  | ||||||
|                         false, |  | ||||||
|                         true, |  | ||||||
|                         SynPat.named lhs, |  | ||||||
|                         rhs, |  | ||||||
|                         [], |  | ||||||
|                         state, |  | ||||||
|                         range0, |  | ||||||
|                         { |  | ||||||
|                             EqualsRange = Some range0 |  | ||||||
|                         } |  | ||||||
|                     ) |  | ||||||
|                 | Let (lhs, rhs) -> createLet [ SynBinding.basic [ Ident.create lhs ] [] rhs ] state |  | ||||||
|                 | Use (lhs, rhs) -> |  | ||||||
|                     SynExpr.LetOrUse ( |  | ||||||
|                         false, |  | ||||||
|                         true, |  | ||||||
|                         [ SynBinding.basic [ Ident.create lhs ] [] rhs ], |  | ||||||
|                         state, |  | ||||||
|                         range0, |  | ||||||
|                         { |  | ||||||
|                             SynExprLetOrUseTrivia.InKeyword = None |  | ||||||
|                         } |  | ||||||
|                     ) |  | ||||||
|                 | Do body -> sequential [ SynExpr.Do (body, range0) ; state ] |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|         applyFunction (createIdent compExpr) (SynExpr.ComputationExpr (false, contents, range0)) |  | ||||||
|  |  | ||||||
|     /// {expr} |> Async.AwaitTask |  | ||||||
|     let awaitTask (expr : SynExpr) : SynExpr = |  | ||||||
|         expr |> pipeThroughFunction (createLongIdent [ "Async" ; "AwaitTask" ]) |  | ||||||
|  |  | ||||||
|     /// {ident}.ToString () |  | ||||||
|     /// with special casing for some types like DateTime |  | ||||||
|     let toString (ty : SynType) (ident : SynExpr) = |  | ||||||
|         match ty with |  | ||||||
|         | DateOnly -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-dd") |  | ||||||
|         | DateTime -> ident |> callMethodArg "ToString" (SynExpr.CreateConst "yyyy-MM-ddTHH:mm:ss") |  | ||||||
|         | _ -> callMethod "ToString" ident |  | ||||||
|  |  | ||||||
|     let upcast' (ty : SynType) (e : SynExpr) = SynExpr.Upcast (e, ty, range0) |  | ||||||
|  |  | ||||||
|     /// {ident} - {rhs} |  | ||||||
|     let minus (ident : SynLongIdent) (rhs : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.sub, SynExpr.CreateLongIdent ident) |  | ||||||
|         |> applyTo rhs |  | ||||||
|  |  | ||||||
|     /// {ident} - {n} |  | ||||||
|     let minusN (ident : SynLongIdent) (n : int) : SynExpr = minus ident (SynExpr.CreateConst n) |  | ||||||
|  |  | ||||||
|     /// {y} > {x} |  | ||||||
|     let greaterThan (x : SynExpr) (y : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.ge, y) |> applyTo x |  | ||||||
|  |  | ||||||
|     /// {y} >= {x} |  | ||||||
|     let greaterThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr = |  | ||||||
|         SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.geq, y) |  | ||||||
|         |> applyTo x |  | ||||||
| @@ -1,10 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynExprLetOrUseTrivia = |  | ||||||
|     let empty : SynExprLetOrUseTrivia = |  | ||||||
|         { |  | ||||||
|             InKeyword = None |  | ||||||
|         } |  | ||||||
| @@ -1,69 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Fantomas.FCS.Xml |  | ||||||
|  |  | ||||||
| type internal SynFieldData<'Ident> = |  | ||||||
|     { |  | ||||||
|         Attrs : SynAttribute list |  | ||||||
|         Ident : 'Ident |  | ||||||
|         Type : SynType |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynField = |  | ||||||
|     /// Get the useful information out of a SynField. |  | ||||||
|     let extract (SynField (attrs, _, id, fieldType, _, _, _, _, _)) : SynFieldData<Ident option> = |  | ||||||
|         { |  | ||||||
|             Attrs = attrs |> List.collect (fun l -> l.Attributes) |  | ||||||
|             Ident = id |  | ||||||
|             Type = fieldType |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     let mapIdent<'a, 'b> (f : 'a -> 'b) (x : SynFieldData<'a>) : SynFieldData<'b> = |  | ||||||
|         let ident = f x.Ident |  | ||||||
|  |  | ||||||
|         { |  | ||||||
|             Attrs = x.Attrs |  | ||||||
|             Ident = ident |  | ||||||
|             Type = x.Type |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     /// Throws if the field has no identifier. |  | ||||||
|     let extractWithIdent (f : SynField) : SynFieldData<Ident> = |  | ||||||
|         f |  | ||||||
|         |> extract |  | ||||||
|         |> mapIdent (fun ident -> |  | ||||||
|             match ident with |  | ||||||
|             | None -> failwith "expected field identifier to have a value, but it did not" |  | ||||||
|             | Some i -> i |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let make (data : SynFieldData<Ident option>) : SynField = |  | ||||||
|         let attrs : SynAttributeList list = |  | ||||||
|             data.Attrs |  | ||||||
|             |> List.map (fun l -> |  | ||||||
|                 { |  | ||||||
|                     Attributes = [ l ] |  | ||||||
|                     Range = range0 |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|         SynField.SynField ( |  | ||||||
|             attrs, |  | ||||||
|             false, |  | ||||||
|             data.Ident, |  | ||||||
|             data.Type, |  | ||||||
|             false, |  | ||||||
|             PreXmlDoc.Empty, |  | ||||||
|             None, |  | ||||||
|             range0, |  | ||||||
|             SynFieldTrivia.Zero |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let withDocString (doc : PreXmlDoc) (f : SynField) : SynField = |  | ||||||
|         match f with |  | ||||||
|         | SynField (attributes, isStatic, idOpt, fieldType, isMutable, _, accessibility, range, trivia) -> |  | ||||||
|             SynField (attributes, isStatic, idOpt, fieldType, isMutable, doc, accessibility, range, trivia) |  | ||||||
| @@ -1,106 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynLongIdent = |  | ||||||
|  |  | ||||||
|     let geq = |  | ||||||
|         SynLongIdent.SynLongIdent ( |  | ||||||
|             [ Ident.create "op_GreaterThanOrEqual" ], |  | ||||||
|             [], |  | ||||||
|             [ Some (IdentTrivia.OriginalNotation ">=") ] |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let ge = |  | ||||||
|         SynLongIdent.SynLongIdent ([ Ident.create "op_GreaterThan" ], [], [ Some (IdentTrivia.OriginalNotation ">") ]) |  | ||||||
|  |  | ||||||
|     let sub = |  | ||||||
|         SynLongIdent.SynLongIdent ([ Ident.create "op_Subtraction" ], [], [ Some (IdentTrivia.OriginalNotation "-") ]) |  | ||||||
|  |  | ||||||
|     let eq = |  | ||||||
|         SynLongIdent.SynLongIdent ([ Ident.create "op_Equality" ], [], [ Some (IdentTrivia.OriginalNotation "=") ]) |  | ||||||
|  |  | ||||||
|     let pipe = |  | ||||||
|         SynLongIdent.SynLongIdent ([ Ident.create "op_PipeRight" ], [], [ Some (IdentTrivia.OriginalNotation "|>") ]) |  | ||||||
|  |  | ||||||
|     let toString (sli : SynLongIdent) : string = |  | ||||||
|         sli.LongIdent |> List.map _.idText |> String.concat "." |  | ||||||
|  |  | ||||||
|     let create (ident : LongIdent) : SynLongIdent = |  | ||||||
|         let commas = |  | ||||||
|             match ident with |  | ||||||
|             | [] -> [] |  | ||||||
|             | _ :: commas -> commas |> List.map (fun _ -> range0) |  | ||||||
|  |  | ||||||
|         SynLongIdent.SynLongIdent (ident, commas, List.replicate ident.Length None) |  | ||||||
|  |  | ||||||
|     let inline createI (i : Ident) : SynLongIdent = create [ i ] |  | ||||||
|  |  | ||||||
|     let inline createS (s : string) : SynLongIdent = createI (Ident (s, range0)) |  | ||||||
|  |  | ||||||
|     let inline createS' (s : string list) : SynLongIdent = |  | ||||||
|         create (s |> List.map (fun i -> Ident (i, range0))) |  | ||||||
|  |  | ||||||
|     let isUnit (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent with |  | ||||||
|         | [ i ] when System.String.Equals (i.idText, "unit", System.StringComparison.OrdinalIgnoreCase) -> true |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isList (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent with |  | ||||||
|         | [ i ] when System.String.Equals (i.idText, "list", System.StringComparison.OrdinalIgnoreCase) -> true |  | ||||||
|         // TODO: consider FSharpList or whatever it is |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isArray (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent with |  | ||||||
|         | [ i ] when |  | ||||||
|             System.String.Equals (i.idText, "array", System.StringComparison.OrdinalIgnoreCase) |  | ||||||
|             || System.String.Equals (i.idText, "[]", System.StringComparison.Ordinal) |  | ||||||
|             -> |  | ||||||
|             true |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isOption (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent with |  | ||||||
|         | [ i ] when System.String.Equals (i.idText, "option", System.StringComparison.OrdinalIgnoreCase) -> true |  | ||||||
|         // TODO: consider Microsoft.FSharp.Option or whatever it is |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isResponse (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent |> List.map _.idText with |  | ||||||
|         | [ "Response" ] |  | ||||||
|         | [ "RestEase" ; "Response" ] -> true |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isMap (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent |> List.map _.idText with |  | ||||||
|         | [ "Map" ] -> true |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isReadOnlyDictionary (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent |> List.map _.idText with |  | ||||||
|         | [ "IReadOnlyDictionary" ] |  | ||||||
|         | [ "Generic" ; "IReadOnlyDictionary" ] |  | ||||||
|         | [ "Collections" ; "Generic" ; "IReadOnlyDictionary" ] |  | ||||||
|         | [ "System" ; "Collections" ; "Generic" ; "IReadOnlyDictionary" ] -> true |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isDictionary (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent |> List.map _.idText with |  | ||||||
|         | [ "Dictionary" ] |  | ||||||
|         | [ "Generic" ; "Dictionary" ] |  | ||||||
|         | [ "Collections" ; "Generic" ; "Dictionary" ] |  | ||||||
|         | [ "System" ; "Collections" ; "Generic" ; "Dictionary" ] -> true |  | ||||||
|         | _ -> false |  | ||||||
|  |  | ||||||
|     let isIDictionary (ident : SynLongIdent) : bool = |  | ||||||
|         match ident.LongIdent |> List.map _.idText with |  | ||||||
|         | [ "IDictionary" ] |  | ||||||
|         | [ "Generic" ; "IDictionary" ] |  | ||||||
|         | [ "Collections" ; "Generic" ; "IDictionary" ] |  | ||||||
|         | [ "System" ; "Collections" ; "Generic" ; "IDictionary" ] -> true |  | ||||||
|         | _ -> false |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynMatchClause = |  | ||||||
|     let create (lhs : SynPat) (rhs : SynExpr) : SynMatchClause = |  | ||||||
|         SynMatchClause.SynMatchClause ( |  | ||||||
|             lhs, |  | ||||||
|             None, |  | ||||||
|             rhs, |  | ||||||
|             range0, |  | ||||||
|             DebugPointAtTarget.Yes, |  | ||||||
|             { |  | ||||||
|                 ArrowRange = Some range0 |  | ||||||
|                 BarRange = Some range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let withWhere (where : SynExpr) (m : SynMatchClause) : SynMatchClause = |  | ||||||
|         match m with |  | ||||||
|         | SynMatchClause (synPat, _, resultExpr, range, debugPointAtTarget, synMatchClauseTrivia) -> |  | ||||||
|             SynMatchClause (synPat, Some where, resultExpr, range, debugPointAtTarget, synMatchClauseTrivia) |  | ||||||
| @@ -1,65 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
| open Fantomas.FCS.Xml |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynMemberDefn = |  | ||||||
|     let private interfaceMemberSlotFlags = |  | ||||||
|         { |  | ||||||
|             SynMemberFlags.IsInstance = true |  | ||||||
|             SynMemberFlags.IsDispatchSlot = true |  | ||||||
|             SynMemberFlags.IsOverrideOrExplicitImpl = false |  | ||||||
|             SynMemberFlags.IsFinal = false |  | ||||||
|             SynMemberFlags.GetterOrSetterIsCompilerGenerated = false |  | ||||||
|             SynMemberFlags.MemberKind = SynMemberKind.Member |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     let abstractMember |  | ||||||
|         (ident : SynIdent) |  | ||||||
|         (typars : SynTyparDecls option) |  | ||||||
|         (arity : SynValInfo) |  | ||||||
|         (xmlDoc : PreXmlDoc) |  | ||||||
|         (returnType : SynType) |  | ||||||
|         : SynMemberDefn |  | ||||||
|         = |  | ||||||
|         let slot = |  | ||||||
|             SynValSig.SynValSig ( |  | ||||||
|                 [], |  | ||||||
|                 ident, |  | ||||||
|                 SynValTyparDecls.SynValTyparDecls (typars, true), |  | ||||||
|                 returnType, |  | ||||||
|                 arity, |  | ||||||
|                 false, |  | ||||||
|                 false, |  | ||||||
|                 xmlDoc, |  | ||||||
|                 None, |  | ||||||
|                 None, |  | ||||||
|                 range0, |  | ||||||
|                 { |  | ||||||
|                     EqualsRange = None |  | ||||||
|                     WithKeyword = None |  | ||||||
|                     InlineKeyword = None |  | ||||||
|                     LeadingKeyword = SynLeadingKeyword.Abstract range0 |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|         SynMemberDefn.AbstractSlot ( |  | ||||||
|             slot, |  | ||||||
|             interfaceMemberSlotFlags, |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 GetSetKeywords = None |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let staticMember (binding : SynBinding) : SynMemberDefn = |  | ||||||
|         let binding = SynBinding.makeStaticMember binding |  | ||||||
|         SynMemberDefn.Member (binding, range0) |  | ||||||
|  |  | ||||||
|     let memberImplementation (binding : SynBinding) : SynMemberDefn = |  | ||||||
|         let binding = SynBinding.makeInstanceMember binding |  | ||||||
|         SynMemberDefn.Member (binding, range0) |  | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynModuleDecl = |  | ||||||
|  |  | ||||||
|     let inline openAny (ident : SynOpenDeclTarget) : SynModuleDecl = SynModuleDecl.Open (ident, range0) |  | ||||||
|  |  | ||||||
|     let inline createLets (bindings : SynBinding list) : SynModuleDecl = |  | ||||||
|         SynModuleDecl.Let (false, bindings, range0) |  | ||||||
|  |  | ||||||
|     let inline createLet (binding : SynBinding) : SynModuleDecl = createLets [ binding ] |  | ||||||
|  |  | ||||||
|     let nestedModule (info : SynComponentInfo) (decls : SynModuleDecl list) : SynModuleDecl = |  | ||||||
|         SynModuleDecl.NestedModule ( |  | ||||||
|             info, |  | ||||||
|             false, |  | ||||||
|             decls, |  | ||||||
|             false, |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 ModuleKeyword = Some range0 |  | ||||||
|                 EqualsRange = Some range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Fantomas.FCS.Xml |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynModuleOrNamespace = |  | ||||||
|  |  | ||||||
|     let createNamespace (name : LongIdent) (decls : SynModuleDecl list) = |  | ||||||
|         SynModuleOrNamespace.SynModuleOrNamespace ( |  | ||||||
|             name, |  | ||||||
|             false, |  | ||||||
|             SynModuleOrNamespaceKind.DeclaredNamespace, |  | ||||||
|             decls, |  | ||||||
|             PreXmlDoc.Empty, |  | ||||||
|             [], |  | ||||||
|             None, |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.Namespace range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
| @@ -1,35 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynPat = |  | ||||||
|     let inline paren (pat : SynPat) : SynPat = SynPat.Paren (pat, range0) |  | ||||||
|  |  | ||||||
|     let inline annotateTypeNoParen (ty : SynType) (pat : SynPat) = SynPat.Typed (pat, ty, range0) |  | ||||||
|  |  | ||||||
|     let inline annotateType (ty : SynType) (pat : SynPat) = paren (annotateTypeNoParen ty pat) |  | ||||||
|  |  | ||||||
|     let inline named (s : string) : SynPat = |  | ||||||
|         SynPat.Named (SynIdent.SynIdent (Ident (s, range0), None), false, None, range0) |  | ||||||
|  |  | ||||||
|     let inline namedI (i : Ident) : SynPat = |  | ||||||
|         SynPat.Named (SynIdent.SynIdent (i, None), false, None, range0) |  | ||||||
|  |  | ||||||
|     let inline identWithArgs (i : LongIdent) (args : SynArgPats) : SynPat = |  | ||||||
|         SynPat.LongIdent (SynLongIdent.create i, None, None, args, None, range0) |  | ||||||
|  |  | ||||||
|     let inline tupleNoParen (elements : SynPat list) : SynPat = |  | ||||||
|         match elements with |  | ||||||
|         | [] -> failwith "Can't tuple no elements in a pattern" |  | ||||||
|         | [ p ] -> p |  | ||||||
|         | elements -> SynPat.Tuple (false, elements, List.replicate (elements.Length - 1) range0, range0) |  | ||||||
|  |  | ||||||
|     let inline tuple (elements : SynPat list) : SynPat = tupleNoParen elements |> paren |  | ||||||
|  |  | ||||||
|     let inline createConst (c : SynConst) = SynPat.Const (c, range0) |  | ||||||
|  |  | ||||||
|     let unit = createConst SynConst.Unit |  | ||||||
|  |  | ||||||
|     let createNull = SynPat.Null range0 |  | ||||||
| @@ -1,239 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynType = |  | ||||||
|     let rec stripOptionalParen (ty : SynType) : SynType = |  | ||||||
|         match ty with |  | ||||||
|         | SynType.Paren (ty, _) -> stripOptionalParen ty |  | ||||||
|         | ty -> ty |  | ||||||
|  |  | ||||||
|     let inline createLongIdent (ident : LongIdent) : SynType = |  | ||||||
|         SynType.LongIdent (SynLongIdent.create ident) |  | ||||||
|  |  | ||||||
|     let inline createLongIdent' (ident : string list) : SynType = |  | ||||||
|         SynType.LongIdent (SynLongIdent.createS' ident) |  | ||||||
|  |  | ||||||
|     let inline named (name : string) = createLongIdent' [ name ] |  | ||||||
|  |  | ||||||
|     let inline app' (name : SynType) (args : SynType list) : SynType = |  | ||||||
|         if args.IsEmpty then |  | ||||||
|             failwith "Type cannot be applied to no arguments" |  | ||||||
|  |  | ||||||
|         SynType.App (name, Some range0, args, List.replicate (args.Length - 1) range0, Some range0, false, range0) |  | ||||||
|  |  | ||||||
|     let inline app (name : string) (args : SynType list) : SynType = app' (named name) args |  | ||||||
|  |  | ||||||
|     let inline appPostfix (name : string) (arg : SynType) : SynType = |  | ||||||
|         SynType.App (named name, None, [ arg ], [], None, true, range0) |  | ||||||
|  |  | ||||||
|     let inline funFromDomain (domain : SynType) (range : SynType) : SynType = |  | ||||||
|         SynType.Fun ( |  | ||||||
|             domain, |  | ||||||
|             range, |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 ArrowRange = range0 |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let inline signatureParamOfType (ty : SynType) (name : Ident option) : SynType = |  | ||||||
|         SynType.SignatureParameter ([], false, name, ty, range0) |  | ||||||
|  |  | ||||||
|     let inline var (ty : SynTypar) : SynType = SynType.Var (ty, range0) |  | ||||||
|  |  | ||||||
|     let unit : SynType = named "unit" |  | ||||||
|     let int : SynType = named "int" |  | ||||||
|  |  | ||||||
|     /// Given ['a1, 'a2] and 'ret, returns 'a1 -> 'a2 -> 'ret. |  | ||||||
|     let toFun (inputs : SynType list) (ret : SynType) : SynType = |  | ||||||
|         (ret, List.rev inputs) ||> List.fold (fun ty input -> funFromDomain input ty) |  | ||||||
|  |  | ||||||
| [<AutoOpen>] |  | ||||||
| module internal SynTypePatterns = |  | ||||||
|     let (|OptionType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isOption ident -> |  | ||||||
|             Some innerType |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|UnitType|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident when SynLongIdent.isUnit ident -> Some () |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|ListType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isList ident -> |  | ||||||
|             Some innerType |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|ArrayType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isArray ident -> |  | ||||||
|             Some innerType |  | ||||||
|         | SynType.Array (1, innerType, _) -> Some innerType |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|RestEaseResponseType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isResponse ident -> |  | ||||||
|             Some innerType |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|DictionaryType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isDictionary ident -> |  | ||||||
|             Some (key, value) |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|IDictionaryType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isIDictionary ident -> |  | ||||||
|             Some (key, value) |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|IReadOnlyDictionaryType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when |  | ||||||
|             SynLongIdent.isReadOnlyDictionary ident |  | ||||||
|             -> |  | ||||||
|             Some (key, value) |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|MapType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent ident, _, [ key ; value ], _, _, _, _) when SynLongIdent.isMap ident -> |  | ||||||
|             Some (key, value) |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|BigInt|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent |> List.map _.idText with |  | ||||||
|             | [ "bigint" ] |  | ||||||
|             | [ "BigInteger" ] |  | ||||||
|             | [ "Numerics" ; "BigInteger" ] |  | ||||||
|             | [ "System" ; "Numerics" ; "BigInteger" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     /// Returns the type, qualified as in e.g. `System.Boolean`. |  | ||||||
|     let (|PrimitiveType|_|) (fieldType : SynType) : LongIdent option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent with |  | ||||||
|             | [ i ] -> Primitives.qualifyType i.idText |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|String|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent with |  | ||||||
|             | [ i ] -> |  | ||||||
|                 [ "string" ] |  | ||||||
|                 |> List.tryFind (fun s -> s = i.idText) |  | ||||||
|                 |> Option.map ignore<string> |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|Byte|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent with |  | ||||||
|             | [ i ] -> [ "byte" ] |> List.tryFind (fun s -> s = i.idText) |> Option.map ignore<string> |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|Guid|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "System" ; "Guid" ] |  | ||||||
|             | [ "Guid" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|HttpResponseMessage|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "System" ; "Net" ; "Http" ; "HttpResponseMessage" ] |  | ||||||
|             | [ "Net" ; "Http" ; "HttpResponseMessage" ] |  | ||||||
|             | [ "Http" ; "HttpResponseMessage" ] |  | ||||||
|             | [ "HttpResponseMessage" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|HttpContent|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "System" ; "Net" ; "Http" ; "HttpContent" ] |  | ||||||
|             | [ "Net" ; "Http" ; "HttpContent" ] |  | ||||||
|             | [ "Http" ; "HttpContent" ] |  | ||||||
|             | [ "HttpContent" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|Stream|_|) (fieldType : SynType) : unit option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "System" ; "IO" ; "Stream" ] |  | ||||||
|             | [ "IO" ; "Stream" ] |  | ||||||
|             | [ "Stream" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|NumberType|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent ident -> |  | ||||||
|             match ident.LongIdent with |  | ||||||
|             | [ i ] -> [ "string" ; "float" ; "int" ; "bool" ] |> List.tryFind (fun s -> s = i.idText) |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|DateOnly|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> |  | ||||||
|             match ident |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "System" ; "DateOnly" ] |  | ||||||
|             | [ "DateOnly" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|DateTime|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> |  | ||||||
|             match ident |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "System" ; "DateTime" ] |  | ||||||
|             | [ "DateTime" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|Uri|_|) (fieldType : SynType) = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> |  | ||||||
|             match ident |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "System" ; "Uri" ] |  | ||||||
|             | [ "Uri" ] -> Some () |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
|  |  | ||||||
|     let (|Task|_|) (fieldType : SynType) : SynType option = |  | ||||||
|         match fieldType with |  | ||||||
|         | SynType.App (SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)), _, args, _, _, _, _) -> |  | ||||||
|             match ident |> List.map (fun i -> i.idText) with |  | ||||||
|             | [ "Task" ] |  | ||||||
|             | [ "Tasks" ; "Task" ] |  | ||||||
|             | [ "Threading" ; "Tasks" ; "Task" ] |  | ||||||
|             | [ "System" ; "Threading" ; "Tasks" ; "Task" ] -> |  | ||||||
|                 match args with |  | ||||||
|                 | [ arg ] -> Some arg |  | ||||||
|                 | _ -> failwithf "Expected Task to be applied to exactly one arg, but got: %+A" args |  | ||||||
|             | _ -> None |  | ||||||
|         | _ -> None |  | ||||||
| @@ -1,27 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.SyntaxTrivia |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynTypeDefn = |  | ||||||
|  |  | ||||||
|     let inline create (componentInfo : SynComponentInfo) (repr : SynTypeDefnRepr) : SynTypeDefn = |  | ||||||
|         SynTypeDefn.SynTypeDefn ( |  | ||||||
|             componentInfo, |  | ||||||
|             repr, |  | ||||||
|             [], |  | ||||||
|             None, |  | ||||||
|             range0, |  | ||||||
|             { |  | ||||||
|                 LeadingKeyword = SynTypeDefnLeadingKeyword.Type range0 |  | ||||||
|                 EqualsRange = Some range0 |  | ||||||
|                 WithKeyword = None |  | ||||||
|             } |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     let inline withMemberDefns (members : SynMemberDefn list) (r : SynTypeDefn) : SynTypeDefn = |  | ||||||
|         match r with |  | ||||||
|         | SynTypeDefn (typeInfo, typeRepr, _, ctor, range, trivia) -> |  | ||||||
|             SynTypeDefn.SynTypeDefn (typeInfo, typeRepr, members, ctor, range, trivia) |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
| open Fantomas.FCS.Text.Range |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynTypeDefnRepr = |  | ||||||
|  |  | ||||||
|     let inline interfaceType (mems : SynMemberDefns) : SynTypeDefnRepr = |  | ||||||
|         SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Unspecified, mems, range0) |  | ||||||
|  |  | ||||||
|     /// Indicates the body of a `type Foo with {body}` extension type declaration. |  | ||||||
|     let inline augmentation () : SynTypeDefnRepr = |  | ||||||
|         SynTypeDefnRepr.ObjectModel (SynTypeDefnKind.Augmentation range0, [], range0) |  | ||||||
|  |  | ||||||
|     let inline union (cases : SynUnionCase list) : SynTypeDefnRepr = |  | ||||||
|         SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (None, cases, range0), range0) |  | ||||||
|  |  | ||||||
|     let inline record (fields : SynField list) : SynTypeDefnRepr = |  | ||||||
|         SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (None, fields, range0), range0) |  | ||||||
| @@ -1,41 +0,0 @@ | |||||||
| namespace WoofWare.Myriad.Plugins |  | ||||||
|  |  | ||||||
| open Fantomas.FCS.Syntax |  | ||||||
|  |  | ||||||
| type internal UnionCase<'Ident> = |  | ||||||
|     { |  | ||||||
|         Fields : SynFieldData<'Ident> list |  | ||||||
|         Attrs : SynAttribute list |  | ||||||
|         Ident : Ident |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal UnionCase = |  | ||||||
|     let mapIdentFields<'a, 'b> (f : 'a -> 'b) (unionCase : UnionCase<'a>) : UnionCase<'b> = |  | ||||||
|         { |  | ||||||
|             Fields = unionCase.Fields |> List.map (SynField.mapIdent f) |  | ||||||
|             Attrs = unionCase.Attrs |  | ||||||
|             Ident = unionCase.Ident |  | ||||||
|         } |  | ||||||
|  |  | ||||||
| [<RequireQualifiedAccess>] |  | ||||||
| module internal SynUnionCase = |  | ||||||
|     let extract (SynUnionCase (attrs, id, caseType, _, _, _, _)) : UnionCase<Ident option> = |  | ||||||
|         match caseType with |  | ||||||
|         | SynUnionCaseKind.FullType _ -> failwith "WoofWare.Myriad does not support FullType union cases." |  | ||||||
|         | SynUnionCaseKind.Fields fields -> |  | ||||||
|  |  | ||||||
|         let fields = fields |> List.map SynField.extract |  | ||||||
|  |  | ||||||
|         let id = |  | ||||||
|             match id with |  | ||||||
|             | SynIdent.SynIdent (ident, _) -> ident |  | ||||||
|  |  | ||||||
|         // As far as I can tell, there's no way to get any attributes here? :shrug: |  | ||||||
|         let attrs = attrs |> List.collect (fun l -> l.Attributes) |  | ||||||
|  |  | ||||||
|         { |  | ||||||
|             Fields = fields |  | ||||||
|             Attrs = attrs |  | ||||||
|             Ident = id |  | ||||||
|         } |  | ||||||
							
								
								
									
										10
									
								
								WoofWare.Myriad.Plugins/SynType.fs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								WoofWare.Myriad.Plugins/SynType.fs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | namespace WoofWare.Myriad.Plugins | ||||||
|  |  | ||||||
|  | open Fantomas.FCS.Syntax | ||||||
|  |  | ||||||
|  | [<RequireQualifiedAccess>] | ||||||
|  | module internal SynType = | ||||||
|  |     let rec stripOptionalParen (ty : SynType) : SynType = | ||||||
|  |         match ty with | ||||||
|  |         | SynType.Paren (ty, _) -> stripOptionalParen ty | ||||||
|  |         | ty -> ty | ||||||
| @@ -25,28 +25,11 @@ | |||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Compile Include="List.fs"/> |     <Compile Include="List.fs"/> | ||||||
|     <Compile Include="Primitives.fs" /> |     <Compile Include="Ident.fs" /> | ||||||
|     <Compile Include="SynExpr\PreXmlDoc.fs" /> |  | ||||||
|     <Compile Include="SynExpr\Ident.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynLongIdent.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynExprLetOrUseTrivia.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynPat.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynBinding.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynType.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynMatchClause.fs" /> |  | ||||||
|     <Compile Include="SynExpr\CompExpr.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynExpr.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynArgPats.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynField.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynUnionCase.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynTypeDefnRepr.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynTypeDefn.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynComponentInfo.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynMemberDefn.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynAttribute.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynModuleDecl.fs" /> |  | ||||||
|     <Compile Include="SynExpr\SynModuleOrNamespace.fs" /> |  | ||||||
|     <Compile Include="AstHelper.fs"/> |     <Compile Include="AstHelper.fs"/> | ||||||
|  |     <Compile Include="SynExpr.fs"/> | ||||||
|  |     <Compile Include="SynType.fs"/> | ||||||
|  |     <Compile Include="SynAttribute.fs"/> | ||||||
|     <Compile Include="RemoveOptionsGenerator.fs"/> |     <Compile Include="RemoveOptionsGenerator.fs"/> | ||||||
|     <Compile Include="InterfaceMockGenerator.fs"/> |     <Compile Include="InterfaceMockGenerator.fs"/> | ||||||
|     <Compile Include="JsonSerializeGenerator.fs"/> |     <Compile Include="JsonSerializeGenerator.fs"/> | ||||||
|   | |||||||
| @@ -3,11 +3,5 @@ | |||||||
|   "publicReleaseRefSpec": [ |   "publicReleaseRefSpec": [ | ||||||
|     "^refs/heads/main$" |     "^refs/heads/main$" | ||||||
|   ], |   ], | ||||||
|   "pathFilters": [ |   "pathFilters": null | ||||||
|     ":/", |  | ||||||
|     ":^WoofWare.Myriad.Plugins.Test/", |  | ||||||
|     ":^WoofWare.Myriad.Plugins.Attributes/Test/", |  | ||||||
|     ":^/.github/", |  | ||||||
|     ":^/CHANGELOG.md" |  | ||||||
|   ] |  | ||||||
| } | } | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.10.0]" /> |     <PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.8.0]" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								flake.nix
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								flake.nix
									
									
									
									
									
								
							| @@ -7,6 +7,7 @@ | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   outputs = { |   outputs = { | ||||||
|  |     self, | ||||||
|     nixpkgs, |     nixpkgs, | ||||||
|     flake-utils, |     flake-utils, | ||||||
|     ... |     ... | ||||||
| @@ -45,19 +46,44 @@ | |||||||
|       packages = { |       packages = { | ||||||
|         fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256; |         fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256; | ||||||
|         fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256; |         fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256; | ||||||
|  |         fetchDeps = let | ||||||
|  |           flags = []; | ||||||
|  |           runtimeIds = ["win-x64"] ++ map (system: pkgs.dotnetCorePackages.systemToDotnetRid system) dotnet-sdk.meta.platforms; | ||||||
|  |         in | ||||||
|  |           pkgs.writeShellScriptBin "fetch-${pname}-deps" (builtins.readFile (pkgs.substituteAll { | ||||||
|  |             src = ./nix/fetchDeps.sh; | ||||||
|  |             pname = pname; | ||||||
|  |             binPath = pkgs.lib.makeBinPath [pkgs.coreutils dotnet-sdk (pkgs.nuget-to-nix.override {inherit dotnet-sdk;})]; | ||||||
|  |             projectFiles = toString ["./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj" "./ConsumePlugin/ConsumePlugin.fsproj" "./WoofWare.Myriad.Plugins.Attributes/WoofWare.Myriad.Plugins.Attributes.fsproj"]; | ||||||
|  |             testProjectFiles = ["./WoofWare.Myriad.Plugins.Test/WoofWare.Myriad.Plugins.Test.fsproj" "./WoofWare.Myriad.Plugins.Attributes/Test/Woofware.Myriad.Plugins.Attributes.Test.fsproj"]; | ||||||
|  |             rids = pkgs.lib.concatStringsSep "\" \"" runtimeIds; | ||||||
|  |             packages = dotnet-sdk.packages; | ||||||
|  |             storeSrc = pkgs.srcOnly { | ||||||
|  |               src = ./.; | ||||||
|  |               pname = pname; | ||||||
|  |               version = version; | ||||||
|  |             }; | ||||||
|  |           })); | ||||||
|         default = pkgs.buildDotnetModule { |         default = pkgs.buildDotnetModule { | ||||||
|           inherit pname version dotnet-sdk dotnet-runtime; |           pname = pname; | ||||||
|           name = "WoofWare.Myriad.Plugins"; |           name = "WoofWare.Myriad.Plugins"; | ||||||
|  |           version = version; | ||||||
|           src = ./.; |           src = ./.; | ||||||
|           projectFile = "./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj"; |           projectFile = "./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj"; | ||||||
|           testProjectFile = "./WoofWare.Myriad.Plugins.Test/WoofWare.Myriad.Plugins.Test.fsproj"; |           nugetDeps = ./nix/deps.nix; | ||||||
|           disabledTests = ["WoofWare.Myriad.Plugins.Test.TestSurface.CheckVersionAgainstRemote"]; |  | ||||||
|           nugetDeps = ./nix/deps.nix; # `nix build .#default.passthru.fetch-deps && ./result` and put the result here |  | ||||||
|           doCheck = true; |           doCheck = true; | ||||||
|  |           dotnet-sdk = dotnet-sdk; | ||||||
|  |           dotnet-runtime = dotnet-runtime; | ||||||
|         }; |         }; | ||||||
|       }; |       }; | ||||||
|       devShell = pkgs.mkShell { |       devShell = pkgs.mkShell { | ||||||
|         buildInputs = [dotnet-sdk]; |         buildInputs = with pkgs; [ | ||||||
|  |           (with dotnetCorePackages; | ||||||
|  |             combinePackages [ | ||||||
|  |               dotnet-sdk_8 | ||||||
|  |               dotnetPackages.Nuget | ||||||
|  |             ]) | ||||||
|  |         ]; | ||||||
|         packages = [ |         packages = [ | ||||||
|           pkgs.alejandra |           pkgs.alejandra | ||||||
|           pkgs.nodePackages.markdown-link-check |           pkgs.nodePackages.markdown-link-check | ||||||
|   | |||||||
							
								
								
									
										214
									
								
								nix/deps.nix
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								nix/deps.nix
									
									
									
									
									
								
							| @@ -1,15 +1,25 @@ | |||||||
| # This file was automatically generated by passthru.fetch-deps. | # This file was automatically generated by passthru.fetch-deps. | ||||||
| # Please dont edit it manually, your changes might get overwritten! | # Please don't edit it manually, your changes might get overwritten! | ||||||
| {fetchNuGet}: [ | {fetchNuGet}: [ | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "ApiSurface"; |     pname = "fsharp-analyzers"; | ||||||
|     version = "4.0.40"; |     version = "0.24.0"; | ||||||
|     sha256 = "1c9z0b6minlripwrjmv4yd5w8zj4lcpak4x41izh7ygx8kgmbvx0"; |     sha256 = "sha256-cNaM/yHI28sHDGamKMrU237ltOyrR+8vPNUImB5RxjU="; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "fantomas"; |     pname = "fantomas"; | ||||||
|     version = "6.3.7"; |     version = "6.3.0-alpha-007"; | ||||||
|     sha256 = "1z1a5bw7vwz6g8nvfgkvx66jnm4hmvn62vbyq0as60nw0jlvaidl"; |     sha256 = "sha256-uZw6h6k/DS4BcYtK9cv8TLS0H8MZDO3WBaPPTdtTgu0="; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "ApiSurface"; | ||||||
|  |     version = "4.0.28"; | ||||||
|  |     sha256 = "1gg0dqbgbb8aqn2lxi5gf2wq969kgskby5wph6m2b3hdkz7265ak"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "coverlet.collector"; | ||||||
|  |     version = "6.0.0"; | ||||||
|  |     sha256 = "12j34vrkmph8lspbafnqmfnj2qvysz1jcrks2khw798s6dwv0j90"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Fantomas.Core"; |     pname = "Fantomas.Core"; | ||||||
| @@ -26,11 +36,6 @@ | |||||||
|     version = "2.16.6"; |     version = "2.16.6"; | ||||||
|     sha256 = "176rwky6b5rk8dzldiz4068p7m9c5y9ygzbhadrs14jkl94pc56n"; |     sha256 = "176rwky6b5rk8dzldiz4068p7m9c5y9ygzbhadrs14jkl94pc56n"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |  | ||||||
|     pname = "fsharp-analyzers"; |  | ||||||
|     version = "0.26.0"; |  | ||||||
|     sha256 = "0xgv5kvbwfdvcp6s8x7xagbbi4s3mqa4ixni6pazqvyflbgnah7b"; |  | ||||||
|   }) |  | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "FSharp.Core"; |     pname = "FSharp.Core"; | ||||||
|     version = "4.3.4"; |     version = "4.3.4"; | ||||||
| @@ -56,26 +61,61 @@ | |||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "1d8nkz24vsm0iy2xm8y5ak2q1w1p99dxyz0y26acs6sfk2na0vm6"; |     sha256 = "1d8nkz24vsm0iy2xm8y5ak2q1w1p99dxyz0y26acs6sfk2na0vm6"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.AspNetCore.App.Ref"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "0yaaiqq7mi6sclyrb1v0fyncanbx0ifmnnhv9whynqj8439jsdwh"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64"; |     pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "1za8lc52m4z54d68wd64c2nhzy05g3gx171k5cdlx73fbymiys9z"; |     sha256 = "1za8lc52m4z54d68wd64c2nhzy05g3gx171k5cdlx73fbymiys9z"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "0dsdgqg7566qximmjfza4x9if3icy4kskq698ddj5apdia88h2mw"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.AspNetCore.App.Runtime.linux-x64"; |     pname = "Microsoft.AspNetCore.App.Runtime.linux-x64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "1zpbmz6z8758gwywzg0bac8kx9x39sxxc9j4a4r2jl74l9ssw4vm"; |     sha256 = "1zpbmz6z8758gwywzg0bac8kx9x39sxxc9j4a4r2jl74l9ssw4vm"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.AspNetCore.App.Runtime.linux-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "1gjz379y61ag9whi78qxx09bwkwcznkx2mzypgycibxk61g11da1"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64"; |     pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "1i8ydlwjzk7j0mzvn0rpljxfp1h50zwaqalnyvfxai1fwgigzgw5"; |     sha256 = "1i8ydlwjzk7j0mzvn0rpljxfp1h50zwaqalnyvfxai1fwgigzgw5"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "0w3mrs4zdl9mfanl1j81759xwwrzmicsjxn6yfxv5yrxbxzq695n"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.AspNetCore.App.Runtime.osx-x64"; |     pname = "Microsoft.AspNetCore.App.Runtime.osx-x64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "02src68hd3213sd1a2ms1my7i92knfmdxclvv90il9cky2zsq8kw"; |     sha256 = "02src68hd3213sd1a2ms1my7i92knfmdxclvv90il9cky2zsq8kw"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.AspNetCore.App.Runtime.osx-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "0a9aljr4fy4haq6ndz2y723liv5hbfpss1rn45s88nmgcp27m15m"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.AspNetCore.App.Runtime.win-x64"; | ||||||
|  |     version = "6.0.26"; | ||||||
|  |     sha256 = "1gxlmfdkfzmhw9pac5jiv674nn6i1zymcp2hj81irjwhhjk01mf5"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.AspNetCore.App.Runtime.win-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "01kzndyqmsvcq49i2jrv7ymfp0l71yxfylv1cy3nhkdbprqz8ipx"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.Build.Tasks.Git"; |     pname = "Microsoft.Build.Tasks.Git"; | ||||||
|     version = "8.0.0"; |     version = "8.0.0"; | ||||||
| @@ -83,59 +123,134 @@ | |||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.CodeCoverage"; |     pname = "Microsoft.CodeCoverage"; | ||||||
|     version = "17.10.0"; |     version = "17.8.0"; | ||||||
|     sha256 = "0s0v7jmrq85n356xv7zixvwa4z94fszjcr5vll8x4im1a2lp00f9"; |     sha256 = "173wjadp3gan4x2jfjchngnc4ca4mb95h1sbb28jydfkfw0z1zvj"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.CodeCoverage"; | ||||||
|  |     version = "17.9.0"; | ||||||
|  |     sha256 = "1gljgi69k0fz8vy8bn6xlyxabj6q4vls2zza9wz7ng6ix3irm89r"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NET.Test.Sdk"; |     pname = "Microsoft.NET.Test.Sdk"; | ||||||
|     version = "17.10.0"; |     version = "17.8.0"; | ||||||
|     sha256 = "13g8fwl09li8fc71nk13dgkb7gahd4qhamyg2xby7am63nlchhdf"; |     sha256 = "1syvl3g0hbrcgfi9rq6pld8s8hqqww4dflf1lxn59ccddyyx0gmv"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NET.Test.Sdk"; | ||||||
|  |     version = "17.9.0"; | ||||||
|  |     sha256 = "1lls1fly2gr1n9n1xyl9k33l2v4pwfmylyzkq8v4v5ldnwkl1zdb"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Host.linux-arm64"; |     pname = "Microsoft.NETCore.App.Host.linux-arm64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "19y6c6v20bgf7x7rrh4rx9y7s5fy8vp5m4j9b6gi1wp4rpb5mza4"; |     sha256 = "19y6c6v20bgf7x7rrh4rx9y7s5fy8vp5m4j9b6gi1wp4rpb5mza4"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Host.linux-arm64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "0dhpdlcdz7adcfh9w01fc867051m35fqaxnvj3fqvqhgcm2n3143"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Host.linux-x64"; |     pname = "Microsoft.NETCore.App.Host.linux-x64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "0p7hhidaa3mnyiwnsijwy8578v843x8hh99255s69qwwyld6falv"; |     sha256 = "0p7hhidaa3mnyiwnsijwy8578v843x8hh99255s69qwwyld6falv"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Host.linux-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "1aw6mc7zcmzs1grxz2wa9cw9kfj8pz7zpj417xnp1a9n4ix1bxgr"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Host.osx-arm64"; |     pname = "Microsoft.NETCore.App.Host.osx-arm64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "1mq11xsv9g1vsasp6k80y7xlvwi9hrpk5dgm773fvy8538s01gfv"; |     sha256 = "1mq11xsv9g1vsasp6k80y7xlvwi9hrpk5dgm773fvy8538s01gfv"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Host.osx-arm64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "1dzg3prng9zfdzz7gcgywjdbwzhwm85j89z0jahynxx4q2dra4b9"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Host.osx-x64"; |     pname = "Microsoft.NETCore.App.Host.osx-x64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "1chac9b4424ihrrnlzvc7qz6j4ymfjyv4kzyazzzw19yhymdkh2s"; |     sha256 = "1chac9b4424ihrrnlzvc7qz6j4ymfjyv4kzyazzzw19yhymdkh2s"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Host.osx-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "010f8wn15s2kv7yyzgys3pv9i1mxw20hpv1ig2zhybjxs8lpj8jj"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Host.win-x64"; | ||||||
|  |     version = "6.0.26"; | ||||||
|  |     sha256 = "0i7g9fsqjnbh9rc6807m57r2idg5pkcw6xjfwhnxkcpgqm96258v"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Host.win-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "1ssj1cyam3nfidm8q82kvh4i3fzm2lzb3bxw6ck09hwhvwh909z4"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Ref"; |     pname = "Microsoft.NETCore.App.Ref"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "12gb52dhg5h9hgnyqh1zgj2w46paxv2pfh33pphl9ajhrdr7hlsb"; |     sha256 = "12gb52dhg5h9hgnyqh1zgj2w46paxv2pfh33pphl9ajhrdr7hlsb"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Ref"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "02r4jg4ha0qksix9v6s3cpmvavmz54gkawkxy9bvknw5ynxhhl1l"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Runtime.linux-arm64"; |     pname = "Microsoft.NETCore.App.Runtime.linux-arm64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "164hfrwqz5dxcbb441lridk4mzcqmarb0b7ckgvqhsvpawyjw88v"; |     sha256 = "164hfrwqz5dxcbb441lridk4mzcqmarb0b7ckgvqhsvpawyjw88v"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Runtime.linux-arm64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "0353whnjgz3sqhzsfrviad3a3db4pk7hl7m4wwppv5mqdg9i9ri5"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Runtime.linux-x64"; |     pname = "Microsoft.NETCore.App.Runtime.linux-x64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "0islayddpnflviqpbq4djc4f3v9nhsa2y76k5x6il3csq5vdw2hq"; |     sha256 = "0islayddpnflviqpbq4djc4f3v9nhsa2y76k5x6il3csq5vdw2hq"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Runtime.linux-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "1g5b30f4l8a1zjjr3b8pk9mcqxkxqwa86362f84646xaj4iw3a4d"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Runtime.osx-arm64"; |     pname = "Microsoft.NETCore.App.Runtime.osx-arm64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "1acn5zw1pxzmcg3c0pbf9hal36fbdh9mvbsiwra7simrk7hzqpdc"; |     sha256 = "1acn5zw1pxzmcg3c0pbf9hal36fbdh9mvbsiwra7simrk7hzqpdc"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Runtime.osx-arm64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "0cdrpdaq5sl3602anfx1p0z0ncx2sjjvl6mgsd6y38g47n7f95jc"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.App.Runtime.osx-x64"; |     pname = "Microsoft.NETCore.App.Runtime.osx-x64"; | ||||||
|     version = "6.0.26"; |     version = "6.0.26"; | ||||||
|     sha256 = "00f9l9dkdz0zv5csaw8fkm6s8ckrj5n9k3ygz12daa22l3bcn6ii"; |     sha256 = "00f9l9dkdz0zv5csaw8fkm6s8ckrj5n9k3ygz12daa22l3bcn6ii"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Runtime.osx-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "1fk1flqp6ji0l4c2gvh83ykndpx7a2nkkgrgkgql3c75j1k2v1s9"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Runtime.win-x64"; | ||||||
|  |     version = "6.0.26"; | ||||||
|  |     sha256 = "0i2p356phfc5y6qnr3vyrzjfi1mrbwfb6g85k4q37bbyxjfp7zl9"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.NETCore.App.Runtime.win-x64"; | ||||||
|  |     version = "8.0.1"; | ||||||
|  |     sha256 = "198576cdkl72xs29zznff9ls763p8pfr0zji7b74dqxd5ga0s3bd"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.NETCore.Platforms"; |     pname = "Microsoft.NETCore.Platforms"; | ||||||
|     version = "1.1.0"; |     version = "1.1.0"; | ||||||
| @@ -168,13 +283,23 @@ | |||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.TestPlatform.ObjectModel"; |     pname = "Microsoft.TestPlatform.ObjectModel"; | ||||||
|     version = "17.10.0"; |     version = "17.8.0"; | ||||||
|     sha256 = "07j69cw8r39533w4p39mnj00kahazz38760in3jfc45kmlcdb26x"; |     sha256 = "0b0i7lmkrcfvim8i3l93gwqvkhhhfzd53fqfnygdqvkg6np0cg7m"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.TestPlatform.ObjectModel"; | ||||||
|  |     version = "17.9.0"; | ||||||
|  |     sha256 = "1kgsl9w9fganbm9wvlkqgk0ag9hfi58z88rkfybc6kvg78bx89ca"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Microsoft.TestPlatform.TestHost"; |     pname = "Microsoft.TestPlatform.TestHost"; | ||||||
|     version = "17.10.0"; |     version = "17.8.0"; | ||||||
|     sha256 = "1bl471s7fx9jycr0cc8rylwf34mrvlg9qn1an6l86nisavfcyb7v"; |     sha256 = "0f5jah93kjkvxwmhwb78lw11m9pkkq9fvf135hpymmmpxqbdh97q"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "Microsoft.TestPlatform.TestHost"; | ||||||
|  |     version = "17.9.0"; | ||||||
|  |     sha256 = "19ffh31a1jxzn8j69m1vnk5hyfz3dbxmflq77b8x82zybiilh5nl"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "Myriad.Core"; |     pname = "Myriad.Core"; | ||||||
| @@ -191,6 +316,11 @@ | |||||||
|     version = "3.6.133"; |     version = "3.6.133"; | ||||||
|     sha256 = "1cdw8krvsnx0n34f7fm5hiiy7bs6h3asvncqcikc0g46l50w2j80"; |     sha256 = "1cdw8krvsnx0n34f7fm5hiiy7bs6h3asvncqcikc0g46l50w2j80"; | ||||||
|   }) |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "NETStandard.Library"; | ||||||
|  |     version = "2.0.0"; | ||||||
|  |     sha256 = "1bc4ba8ahgk15m8k4nd7x406nhi0kwqzbgjk2dmw52ss553xz7iy"; | ||||||
|  |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NETStandard.Library"; |     pname = "NETStandard.Library"; | ||||||
|     version = "2.0.3"; |     version = "2.0.3"; | ||||||
| @@ -208,38 +338,48 @@ | |||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NuGet.Common"; |     pname = "NuGet.Common"; | ||||||
|     version = "6.10.0"; |     version = "6.8.0"; | ||||||
|     sha256 = "0nizrnilmlcqbm945293h8q3wfqfchb4xi8g50x4kjn0rbpd1kbh"; |     sha256 = "0l3ij8iwy7wj6s7f93lzi9168r4wz8zyin6a08iwgk7hvq44cia1"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NuGet.Configuration"; |     pname = "NuGet.Configuration"; | ||||||
|     version = "6.10.0"; |     version = "6.8.0"; | ||||||
|     sha256 = "1aqaknaawnqx4mnvx9qw73wvj48jjzv0d78dzwl7m9zjlrl9myhz"; |     sha256 = "0x03p408smkmv1gv7pmvsia4lkn0xaj4wfrkl58pjf8bbv51y0yw"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NuGet.Frameworks"; |     pname = "NuGet.Frameworks"; | ||||||
|     version = "6.10.0"; |     version = "6.5.0"; | ||||||
|     sha256 = "0hrd8y31zx9a0wps49czw0qgbrakb49zn3abfgylc9xrq990zkqk"; |     sha256 = "0s37d1p4md0k6d4cy6sq36f2dgkd9qfbzapxhkvi8awwh0vrynhj"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "NuGet.Frameworks"; | ||||||
|  |     version = "6.8.0"; | ||||||
|  |     sha256 = "0i2xvhgkjkjr496i3pg8hamwv6505fia45qhn7jg5m01wb3cvsjl"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NuGet.Packaging"; |     pname = "NuGet.Packaging"; | ||||||
|     version = "6.10.0"; |     version = "6.8.0"; | ||||||
|     sha256 = "18s53cvrf51lihmaqqdf48p2qi6ky1l48jv0hvbp76cxwdg7rba4"; |     sha256 = "031z4s905bxi94h3f0qy4j1b6jxdxgqgpkzqvvpfxch07szxcbim"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NuGet.Protocol"; |     pname = "NuGet.Protocol"; | ||||||
|     version = "6.10.0"; |     version = "6.7.0"; | ||||||
|     sha256 = "0hmv4q0ks9i34mfgpb13l01la9v3jjllfh1qd3aqv105xrqrdxac"; |     sha256 = "1v5ibnq2mp801vw68zyj169hkj3xm7h55824i33n1jxxj2vs3vbk"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NuGet.Versioning"; |     pname = "NuGet.Versioning"; | ||||||
|     version = "6.10.0"; |     version = "6.8.0"; | ||||||
|     sha256 = "1x19njx4x0sw9fz8y5fibi15xfsrw5avir0cx0599yd7p3ykik5g"; |     sha256 = "1sd25h46fd12ng780r02q4ijcx1imkb53kj1y2y7cwg5myh537ks"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NUnit"; |     pname = "NUnit"; | ||||||
|     version = "4.1.0"; |     version = "3.13.3"; | ||||||
|     sha256 = "0fj6xwgqaxq3mrai86bklclfmjkzf038mrslwfqf4ignaz9f7g5j"; |     sha256 = "0wdzfkygqnr73s6lpxg5b1pwaqz9f414fxpvpdmf72bvh4jaqzv6"; | ||||||
|  |   }) | ||||||
|  |   (fetchNuGet { | ||||||
|  |     pname = "NUnit"; | ||||||
|  |     version = "4.0.1"; | ||||||
|  |     sha256 = "0jgiq3dbwli5r70j0bw7021d69r7bhr58s8kphlpjmf7k47l5pcd"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "NUnit3TestAdapter"; |     pname = "NUnit3TestAdapter"; | ||||||
| @@ -333,12 +473,12 @@ | |||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "System.Text.Encodings.Web"; |     pname = "System.Text.Encodings.Web"; | ||||||
|     version = "7.0.0"; |     version = "6.0.0"; | ||||||
|     sha256 = "1151hbyrcf8kyg1jz8k9awpbic98lwz9x129rg7zk1wrs6vjlpxl"; |     sha256 = "06n9ql3fmhpjl32g3492sj181zjml5dlcc5l76xq2h38c4f87sai"; | ||||||
|   }) |   }) | ||||||
|   (fetchNuGet { |   (fetchNuGet { | ||||||
|     pname = "System.Text.Json"; |     pname = "System.Text.Json"; | ||||||
|     version = "7.0.3"; |     version = "6.0.0"; | ||||||
|     sha256 = "0zjrnc9lshagm6kdb9bdh45dmlnkpwcpyssa896sda93ngbmj8k9"; |     sha256 = "1si2my1g0q0qv1hiqnji4xh9wd05qavxnzj9dwgs23iqvgjky0gl"; | ||||||
|   }) |   }) | ||||||
| ] | ] | ||||||
|   | |||||||
							
								
								
									
										73
									
								
								nix/fetchDeps.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								nix/fetchDeps.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | # This file was adapted from | ||||||
|  | # https://github.com/NixOS/nixpkgs/blob/b981d811453ab84fb3ea593a9b33b960f1ab9147/pkgs/build-support/dotnet/build-dotnet-module/default.nix#L173 | ||||||
|  | set -euo pipefail | ||||||
|  | export PATH="@binPath@" | ||||||
|  | for arg in "$@"; do | ||||||
|  |     case "$arg" in | ||||||
|  |         --keep-sources|-k) | ||||||
|  |             keepSources=1 | ||||||
|  |             shift | ||||||
|  |             ;; | ||||||
|  |         --help|-h) | ||||||
|  |             echo "usage: $0 [--keep-sources] [--help] <output path>" | ||||||
|  |             echo "    <output path>   The path to write the lockfile to. A temporary file is used if this is not set" | ||||||
|  |             echo "    --keep-sources  Don't remove temporary directories upon exit, useful for debugging" | ||||||
|  |             echo "    --help          Show this help message" | ||||||
|  |             exit | ||||||
|  |             ;; | ||||||
|  |     esac | ||||||
|  | done | ||||||
|  | tmp=$(mktemp -td "@pname@-tmp-XXXXXX") | ||||||
|  | export tmp | ||||||
|  | HOME=$tmp/home | ||||||
|  | exitTrap() { | ||||||
|  |     test -n "${ranTrap-}" && return | ||||||
|  |     ranTrap=1 | ||||||
|  |     if test -n "${keepSources-}"; then | ||||||
|  |         echo -e "Path to the source: $tmp/src\nPath to the fake home: $tmp/home" | ||||||
|  |     else | ||||||
|  |         rm -rf "$tmp" | ||||||
|  |     fi | ||||||
|  |     # Since mktemp is used this will be empty if the script didnt succesfully complete | ||||||
|  |     if ! test -s "$depsFile"; then | ||||||
|  |       rm -rf "$depsFile" | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  | trap exitTrap EXIT INT TERM | ||||||
|  | dotnetRestore() { | ||||||
|  |     local -r project="${1-}" | ||||||
|  |     local -r rid="$2" | ||||||
|  |     dotnet restore "${project-}" \ | ||||||
|  |         -p:ContinuousIntegrationBuild=true \ | ||||||
|  |         -p:Deterministic=true \ | ||||||
|  |         --packages "$tmp/nuget_pkgs" \ | ||||||
|  |         --runtime "$rid" \ | ||||||
|  |         --no-cache \ | ||||||
|  |         --force | ||||||
|  | } | ||||||
|  | declare -a projectFiles=( @projectFiles@ ) | ||||||
|  | declare -a testProjectFiles=( @testProjectFiles@ ) | ||||||
|  | export DOTNET_NOLOGO=1 | ||||||
|  | export DOTNET_CLI_TELEMETRY_OPTOUT=1 | ||||||
|  | depsFile=$(realpath "${1:-$(mktemp -t "@pname@-deps-XXXXXX.nix")}") | ||||||
|  | mkdir -p "$tmp/nuget_pkgs" | ||||||
|  | storeSrc="@storeSrc@" | ||||||
|  | src="$tmp/src" | ||||||
|  | cp -rT "$storeSrc" "$src" | ||||||
|  | chmod -R +w "$src" | ||||||
|  | cd "$src" | ||||||
|  | echo "Restoring project..." | ||||||
|  | rids=("@rids@") | ||||||
|  | for rid in "${rids[@]}"; do | ||||||
|  |     (( ${#projectFiles[@]} == 0 )) && dotnetRestore "" "$rid" | ||||||
|  |     for project in "${projectFiles[@]-}" "${testProjectFiles[@]-}"; do | ||||||
|  |         dotnetRestore "$project" "$rid" | ||||||
|  |     done | ||||||
|  | done | ||||||
|  | echo "Successfully restored project" | ||||||
|  | echo "Writing lockfile..." | ||||||
|  | echo -e "# This file was automatically generated by passthru.fetch-deps.\n# Please don't edit it manually, your changes might get overwritten!\n" > "$depsFile" | ||||||
|  | nuget-to-nix "$tmp/nuget_pkgs" "@packages@" >> "$depsFile" | ||||||
|  | echo "Successfully wrote lockfile to $depsFile" | ||||||
		Reference in New Issue
	
	Block a user