Compare commits

...

65 Commits

Author SHA1 Message Date
dependabot[bot]
325f8634a4 Bump FSharp.Core and WoofWare.Whippet.Fantomas (#361)
* Bump FsCheck and FSharp.Core

Bumps [FsCheck](https://github.com/Fscheck/fscheck) and [FSharp.Core](https://github.com/dotnet/fsharp). These dependencies needed to be updated together.

Updates `FsCheck` from 3.1.0 to 3.2.0
- [Release notes](https://github.com/Fscheck/fscheck/releases)
- [Changelog](https://github.com/fscheck/FsCheck/blob/master/FsCheck%20Release%20Notes.md)
- [Commits](https://github.com/Fscheck/fscheck/compare/3.1.0...3.2.0)

Updates `FSharp.Core` from 4.3.4 to 5.0.2
- [Release notes](https://github.com/dotnet/fsharp/releases)
- [Changelog](https://github.com/dotnet/fsharp/blob/main/release-notes.md)
- [Commits](https://github.com/dotnet/fsharp/commits)

---
updated-dependencies:
- dependency-name: FsCheck
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: FSharp.Core
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump FSharp.Core and WoofWare.Whippet.Fantomas

Bumps [FSharp.Core](https://github.com/dotnet/fsharp) and [WoofWare.Whippet.Fantomas](https://github.com/Smaug123/WoofWare.Whippet). These dependencies needed to be updated together.

Updates `FSharp.Core` from 4.3.4 to 6.0.1
- [Release notes](https://github.com/dotnet/fsharp/releases)
- [Changelog](https://github.com/dotnet/fsharp/blob/main/release-notes.md)
- [Commits](https://github.com/dotnet/fsharp/commits)

Updates `WoofWare.Whippet.Fantomas` from 0.3.2 to 0.5.1
- [Commits](https://github.com/Smaug123/WoofWare.Whippet/commits)

---
updated-dependencies:
- dependency-name: FSharp.Core
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: WoofWare.Whippet.Fantomas
  dependency-version: 0.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-04-14 22:05:23 +00:00
Patrick Stevens
3e5d663544 Better docs on PositionalArgsAttribute (#362) 2025-04-14 23:01:26 +01:00
patrick-conscriptus[bot]
bb88f80c85 Automated commit (#358)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-04-13 02:53:09 +00:00
dependabot[bot]
71f26930c6 Bump actions/create-github-app-token from 1 to 2 (#357) 2025-04-07 17:19:12 +01:00
patrick-conscriptus[bot]
680728a06e Automated commit (#356)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-04-06 01:29:18 +00:00
dependabot[bot]
cdc6f2d511 Bump fsharp-analyzers from 0.29.1 to 0.30.0 (#355)
* Bump fsharp-analyzers from 0.29.1 to 0.30.0

Bumps [fsharp-analyzers](https://github.com/ionide/FSharp.Analyzers.SDK) from 0.29.1 to 0.30.0.
- [Release notes](https://github.com/ionide/FSharp.Analyzers.SDK/releases)
- [Changelog](https://github.com/ionide/FSharp.Analyzers.SDK/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ionide/FSharp.Analyzers.SDK/compare/v0.29.1...v0.30.0)

---
updated-dependencies:
- dependency-name: fsharp-analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-04-01 08:23:43 +00:00
patrick-conscriptus[bot]
3be487c328 Automated commit (#354)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-03-30 01:30:44 +00:00
dependabot[bot]
a5f4d169ca Bump FSharp.Core and WoofWare.Whippet.Fantomas (#352)
* Bump FSharp.Core and WoofWare.Whippet.Fantomas

Bumps [FSharp.Core](https://github.com/dotnet/fsharp) and [WoofWare.Whippet.Fantomas](https://github.com/Smaug123/WoofWare.Whippet). These dependencies needed to be updated together.

Updates `FSharp.Core` from 4.3.4 to 6.0.1
- [Release notes](https://github.com/dotnet/fsharp/releases)
- [Changelog](https://github.com/dotnet/fsharp/blob/main/release-notes.md)
- [Commits](https://github.com/dotnet/fsharp/commits)

Updates `WoofWare.Whippet.Fantomas` from 0.3.1 to 0.3.2
- [Commits](https://github.com/Smaug123/WoofWare.Whippet/commits)

---
updated-dependencies:
- dependency-name: FSharp.Core
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: WoofWare.Whippet.Fantomas
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ApiSurface and FSharp.Core

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) and [FSharp.Core](https://github.com/Microsoft/visualfsharp). These dependencies needed to be updated together.

Updates `ApiSurface` from 4.1.17 to 4.1.20
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.17...ApiSurface.4.1.20)

Updates `FSharp.Core` from 4.3.4 to 4.3.4
- [Release notes](https://github.com/Microsoft/visualfsharp/releases)
- [Changelog](https://github.com/dotnet/fsharp/blob/main/release-notes.md)
- [Commits](https://github.com/Microsoft/visualfsharp/commits)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: FSharp.Core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-03-24 19:38:01 +00:00
patrick-conscriptus[bot]
ce634efff2 Automated commit (#351)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-03-23 01:28:44 +00:00
Patrick Stevens
1529dd1fb2 Bump NBGV (#350) 2025-03-21 14:33:32 +00:00
dependabot[bot]
59558b0766 Bump cachix/install-nix-action from 30 to 31 (#349)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 30 to 31.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v30...v31)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 19:56:20 +00:00
dependabot[bot]
8602894efc Bump fsharp-analyzers from 0.29.0 to 0.29.1 (#348)
* Bump fsharp-analyzers from 0.29.0 to 0.29.1

Bumps [fsharp-analyzers](https://github.com/ionide/FSharp.Analyzers.SDK) from 0.29.0 to 0.29.1.
- [Release notes](https://github.com/ionide/FSharp.Analyzers.SDK/releases)
- [Changelog](https://github.com/ionide/FSharp.Analyzers.SDK/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ionide/FSharp.Analyzers.SDK/compare/v0.29.0...v0.29.1)

---
updated-dependencies:
- dependency-name: fsharp-analyzers
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-03-10 18:41:51 +00:00
dependabot[bot]
51d349b365 Bump actions/attest-build-provenance from 2.2.2 to 2.2.3 (#347) 2025-03-10 12:13:39 +00:00
dependabot[bot]
120df84bbf Bump actions/attest-build-provenance from 2.2.0 to 2.2.2 (#345) 2025-03-03 11:24:42 +00:00
dependabot[bot]
603f875a12 Bump ApiSurface and FSharp.Core (#341)
* Automated commit

* Bump Microsoft.NET.Test.Sdk from 17.12.0 to 17.13.0

Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.12.0 to 17.13.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.12.0...v17.13.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ApiSurface and FSharp.Core

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) and [FSharp.Core](https://github.com/Microsoft/visualfsharp). These dependencies needed to be updated together.

Updates `ApiSurface` from 4.1.16 to 4.1.17
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.16...ApiSurface.4.1.17)

Updates `FSharp.Core` from 4.3.4 to 4.3.4
- [Release notes](https://github.com/Microsoft/visualfsharp/releases)
- [Changelog](https://github.com/dotnet/fsharp/blob/main/release-notes.md)
- [Commits](https://github.com/Microsoft/visualfsharp/commits)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: FSharp.Core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump fantomas from 7.0.0 to 7.0.1

Bumps [fantomas](https://github.com/fsprojects/fantomas) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/fsprojects/fantomas/releases)
- [Changelog](https://github.com/fsprojects/fantomas/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fsprojects/fantomas/compare/v7.0.0...v7.0.1)

---
updated-dependencies:
- dependency-name: fantomas
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump NUnit3TestAdapter from 4.6.0 to 5.0.0

Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 4.6.0 to 5.0.0.
- [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases)
- [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V4.6.0...V5.0.0)

---
updated-dependencies:
- dependency-name: NUnit3TestAdapter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

* Suppress build warning

* Revert "Merge remote-tracking branch 'origin/auto_pr2025_02_23-01_20_56_533960' into dependabot/nuget/multi-be38daf731"

This reverts commit d2bb029b2b, reversing
changes made to 7a2fe4a014.

* Deps

* Revert

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-02-25 00:28:26 +00:00
dependabot[bot]
2df41555de Bump fsharp-analyzers from 0.28.0 to 0.29.0, and FsUnit (#338)
* Bump fsharp-analyzers from 0.28.0 to 0.29.0

Bumps [fsharp-analyzers](https://github.com/ionide/FSharp.Analyzers.SDK) from 0.28.0 to 0.29.0.
- [Release notes](https://github.com/ionide/FSharp.Analyzers.SDK/releases)
- [Changelog](https://github.com/ionide/FSharp.Analyzers.SDK/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ionide/FSharp.Analyzers.SDK/compare/v0.28.0...v0.29.0)

---
updated-dependencies:
- dependency-name: fsharp-analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump analysers

* Deps

* Upgrade

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-02-20 10:44:45 +00:00
patrick-conscriptus[bot]
49e31e52b5 Automated commit (#337)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-02-16 01:25:03 +00:00
Patrick Stevens
277a186fda Allow properties in mocked interfaces (#336) 2025-02-12 23:53:15 +00:00
patrick-conscriptus[bot]
129687ec1c Automated commit (#334)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-02-09 01:22:26 +00:00
dependabot[bot]
c7fea55e28 Bump FsCheck from 3.0.1 to 3.1.0 (#333)
* Bump FsCheck from 3.0.1 to 3.1.0

Bumps [FsCheck](https://github.com/Fscheck/fscheck) from 3.0.1 to 3.1.0.
- [Release notes](https://github.com/Fscheck/fscheck/releases)
- [Changelog](https://github.com/fscheck/FsCheck/blob/master/FsCheck%20Release%20Notes.md)
- [Commits](https://github.com/Fscheck/fscheck/compare/3.0.1...3.1.0)

---
updated-dependencies:
- dependency-name: FsCheck
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-02-03 17:28:07 +00:00
patrick-conscriptus[bot]
ded7b32771 Automated commit (#332)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-02-02 01:21:17 +00:00
dependabot[bot]
b272f8b645 Bump FsCheck from 3.0.0 to 3.0.1 (#330)
* Bump FsCheck from 3.0.0 to 3.0.1

Bumps [FsCheck](https://github.com/Fscheck/fscheck) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/Fscheck/fscheck/releases)
- [Changelog](https://github.com/fscheck/FsCheck/blob/master/FsCheck%20Release%20Notes.md)
- [Commits](https://github.com/Fscheck/fscheck/compare/3.0.0...3.0.1)

---
updated-dependencies:
- dependency-name: FsCheck
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-01-29 00:49:28 +00:00
dependabot[bot]
b8d60aec90 Bump actions/attest-build-provenance from 2.1.0 to 2.2.0 (#331) 2025-01-27 11:36:25 +00:00
patrick-conscriptus[bot]
0e3510e1e5 Automated commit (#329)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-01-26 01:19:46 +00:00
patrick-conscriptus[bot]
8a1edd90d5 Automated commit (#328)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-01-19 01:22:30 +00:00
dependabot[bot]
74fdd7c0a9 Bump fantomas from 6.3.16 to 7.0.0 (#326)
* Bump fantomas from 6.3.16 to 7.0.0

Bumps [fantomas](https://github.com/fsprojects/fantomas) from 6.3.16 to 7.0.0.
- [Release notes](https://github.com/fsprojects/fantomas/releases)
- [Changelog](https://github.com/fsprojects/fantomas/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fsprojects/fantomas/compare/v6.3.16...v7.0.0)

---
updated-dependencies:
- dependency-name: fantomas
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

* Format

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-01-14 10:35:58 +00:00
dependabot[bot]
23f55814f9 Bump ApiSurface from 4.1.15 to 4.1.16 (#325)
* Bump FsCheck from 2.16.6 to 3.0.0

Bumps [FsCheck](https://github.com/Fscheck/fscheck) from 2.16.6 to 3.0.0.
- [Release notes](https://github.com/Fscheck/fscheck/releases)
- [Changelog](https://github.com/fscheck/FsCheck/blob/master/FsCheck%20Release%20Notes.md)
- [Commits](https://github.com/Fscheck/fscheck/compare/2.16.6...3.0.0)

---
updated-dependencies:
- dependency-name: FsCheck
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ApiSurface from 4.1.15 to 4.1.16

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.15 to 4.1.16.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.15...ApiSurface.4.1.16)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump Nerdbank.GitVersioning from 3.7.112 to 3.7.115

Bumps [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning) from 3.7.112 to 3.7.115.
- [Release notes](https://github.com/dotnet/Nerdbank.GitVersioning/releases)
- [Commits](https://github.com/dotnet/Nerdbank.GitVersioning/commits)

---
updated-dependencies:
- dependency-name: Nerdbank.GitVersioning
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Lockfile

* Fix tests

* Fix

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2025-01-14 01:16:20 +00:00
Patrick Stevens
15c04bb373 Use GR's GitHub release action (#323) 2025-01-13 09:34:27 +00:00
patrick-conscriptus[bot]
a860a93f9c Automated commit (#322)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-01-12 01:25:56 +00:00
patrick-conscriptus[bot]
b056af348e Automated commit (#321)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2025-01-05 01:24:38 +00:00
dependabot[bot]
b44c8db6e9 Bump NUnit from 4.3.1 to 4.3.2 (#320)
* Bump NUnit from 4.3.1 to 4.3.2

Bumps [NUnit](https://github.com/nunit/nunit) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/4.3.1...4.3.2)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-12-30 22:43:17 +00:00
patrick-conscriptus[bot]
7d6a2cea01 Automated commit (#319)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-12-29 01:25:23 +00:00
Patrick Stevens
d779a602f4 Fix flake update after recent nixpkgs bump (#318) 2024-12-24 19:49:30 +00:00
Patrick Stevens
23cd5272fb Use non-deprecated nixpkgs methods (#317) 2024-12-24 19:32:39 +00:00
dependabot[bot]
93538ee6b4 Bump NUnit from 4.3.0 to 4.3.1 (#315)
* Bump NUnit from 4.3.0 to 4.3.1

Bumps [NUnit](https://github.com/nunit/nunit) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/4.3.0...4.3.1)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ApiSurface from 4.1.14 to 4.1.15

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.14 to 4.1.15.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.14...ApiSurface.4.1.15)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-12-23 11:45:33 +00:00
patrick-conscriptus[bot]
8a29c2f444 Automated commit (#314)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-12-22 01:24:49 +00:00
dependabot[bot]
1367e00f34 Bump Nerdbank.GitVersioning from 3.6.146 to 3.7.112 (#311)
* Bump NUnit from 4.2.2 to 4.3.0

Bumps [NUnit](https://github.com/nunit/nunit) from 4.2.2 to 4.3.0.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/4.2.2...4.3.0)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump Nerdbank.GitVersioning from 3.6.146 to 3.7.112

Bumps [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning) from 3.6.146 to 3.7.112.
- [Release notes](https://github.com/dotnet/Nerdbank.GitVersioning/releases)
- [Commits](https://github.com/dotnet/Nerdbank.GitVersioning/compare/v3.6.146...v3.7.112)

---
updated-dependencies:
- dependency-name: Nerdbank.GitVersioning
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ApiSurface from 4.1.12 to 4.1.14

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.12 to 4.1.14.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.12...ApiSurface.4.1.14)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-12-16 11:21:31 +00:00
dependabot[bot]
bff08c90cd Bump actions/attest-build-provenance from 2.0.1 to 2.1.0 (#313)
Bumps [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) from 2.0.1 to 2.1.0.
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](c4fbc64884...7668571508)

---
updated-dependencies:
- dependency-name: actions/attest-build-provenance
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 10:55:25 +00:00
Patrick Stevens
4136f7fe94 Update to net9 SDK (#302) 2024-12-15 22:13:30 +00:00
patrick-conscriptus[bot]
9fe2e3b1fa Automated commit (#309)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-12-15 01:31:17 +00:00
dependabot[bot]
13a597a365 Bump actions/attest-build-provenance from 1.4.4 to 2.0.1 (#308) 2024-12-09 13:45:39 +00:00
patrick-conscriptus[bot]
3acc492f22 Automated commit (#307)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-12-08 01:32:11 +00:00
patrick-conscriptus[bot]
eefe64f5a4 Automated commit (#306)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-12-01 01:44:12 +00:00
dependabot[bot]
93a2d92299 Bump fsharp-analyzers from 0.27.0 to 0.28.0 (#305)
* Bump ApiSurface from 4.1.11 to 4.1.12

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.11 to 4.1.12.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.11...ApiSurface.4.1.12)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump Microsoft.NET.Test.Sdk from 17.11.1 to 17.12.0

Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.11.1 to 17.12.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.11.1...v17.12.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump fsharp-analyzers from 0.27.0 to 0.28.0

Bumps [fsharp-analyzers](https://github.com/ionide/FSharp.Analyzers.SDK) from 0.27.0 to 0.28.0.
- [Release notes](https://github.com/ionide/FSharp.Analyzers.SDK/releases)
- [Changelog](https://github.com/ionide/FSharp.Analyzers.SDK/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ionide/FSharp.Analyzers.SDK/compare/v0.27.0...v0.28.0)

---
updated-dependencies:
- dependency-name: fsharp-analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

* Fix flake

* Fix analysers

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-11-25 16:38:14 +00:00
patrick-conscriptus[bot]
33793e8cbe Automated commit (#301)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-11-24 01:28:15 +00:00
dependabot[bot]
fa7ef1ffba Bump ApiSurface from 4.1.8 to 4.1.11 (#300)
* Bump ApiSurface from 4.1.8 to 4.1.11

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.8 to 4.1.11.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.8...ApiSurface.4.1.11)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-11-18 20:07:55 +00:00
patrick-conscriptus[bot]
a25c45dc3a Automated commit (#299)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-11-17 01:26:53 +00:00
dependabot[bot]
af5f2abdf8 Bump actions/attest-build-provenance from 1.4.3 to 1.4.4 (#298)
Bumps [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) from 1.4.3 to 1.4.4.
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](1c608d11d6...ef244123eb)

---
updated-dependencies:
- dependency-name: actions/attest-build-provenance
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 11:07:51 +00:00
patrick-conscriptus[bot]
0f89816432 Automated commit (#297)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-11-10 01:22:22 +00:00
dependabot[bot]
d571da6a22 Bump fantomas from 6.3.15 to 6.3.16 (#296)
* Bump fantomas from 6.3.15 to 6.3.16

Bumps [fantomas](https://github.com/fsprojects/fantomas) from 6.3.15 to 6.3.16.
- [Release notes](https://github.com/fsprojects/fantomas/releases)
- [Changelog](https://github.com/fsprojects/fantomas/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fsprojects/fantomas/compare/v6.3.15...v6.3.16)

---
updated-dependencies:
- dependency-name: fantomas
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-11-04 17:42:25 +00:00
patrick-conscriptus[bot]
39a9e94ca5 Automated commit (#295)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-11-03 01:24:04 +00:00
patrick-conscriptus[bot]
487f73312a Automated commit (#294)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-10-27 01:24:19 +00:00
dependabot[bot]
b7aa564306 Bump Nerdbank.GitVersioning from 3.6.143 to 3.6.146 (#292)
* Bump Nerdbank.GitVersioning from 3.6.143 to 3.6.146

Bumps [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning) from 3.6.143 to 3.6.146.
- [Release notes](https://github.com/dotnet/Nerdbank.GitVersioning/releases)
- [Commits](https://github.com/dotnet/Nerdbank.GitVersioning/commits)

---
updated-dependencies:
- dependency-name: Nerdbank.GitVersioning
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ApiSurface from 4.1.7 to 4.1.8

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.7 to 4.1.8.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.7...ApiSurface.4.1.8)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-10-21 19:29:38 +01:00
patrick-conscriptus[bot]
a34dee0a1c Automated commit (#291)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-10-20 01:24:50 +00:00
dependabot[bot]
44506f3650 Bump WoofWare.Whippet.Fantomas and FSharp.Core (#289)
* Bump WoofWare.Whippet.Fantomas and FSharp.Core

Bumps [WoofWare.Whippet.Fantomas](https://github.com/Smaug123/WoofWare.Whippet) and [FSharp.Core](https://github.com/dotnet/fsharp). These dependencies needed to be updated together.

Updates `WoofWare.Whippet.Fantomas` from 0.2.1 to 0.3.1
- [Commits](https://github.com/Smaug123/WoofWare.Whippet/commits)

Updates `FSharp.Core` from 4.3.4 to 6.0.1
- [Release notes](https://github.com/dotnet/fsharp/releases)
- [Changelog](https://github.com/dotnet/fsharp/blob/main/release-notes.md)
- [Commits](https://github.com/dotnet/fsharp/commits)

---
updated-dependencies:
- dependency-name: WoofWare.Whippet.Fantomas
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: FSharp.Core
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-10-14 11:39:41 +00:00
dependabot[bot]
ca7134cfb8 Bump ApiSurface from 4.1.6 to 4.1.7 (#290)
* Bump ApiSurface from 4.1.6 to 4.1.7

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.6...ApiSurface.4.1.7)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-10-14 11:30:54 +00:00
patrick-conscriptus[bot]
773fd088a7 Automated commit (#288)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-10-13 01:23:21 +00:00
dependabot[bot]
6e5c0332cd Bump ApiSurface from 4.1.5 to 4.1.6 (#286)
* Bump ApiSurface from 4.1.5 to 4.1.6

Bumps [ApiSurface](https://github.com/G-Research/ApiSurface) from 4.1.5 to 4.1.6.
- [Release notes](https://github.com/G-Research/ApiSurface/releases)
- [Commits](https://github.com/G-Research/ApiSurface/compare/ApiSurface.4.1.5...ApiSurface.4.1.6)

---
updated-dependencies:
- dependency-name: ApiSurface
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* deps

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Smaug123 <3138005+Smaug123@users.noreply.github.com>
2024-10-07 21:12:40 +01:00
Patrick Stevens
aece186424 Fix NuGet packaging (#287) 2024-10-07 20:38:49 +01:00
dependabot[bot]
827e9aa3ec Bump cachix/install-nix-action from 29 to 30 (#285)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 29 to 30.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v29...v30)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 12:30:06 +01:00
Patrick Stevens
d59ebdfccb Use more of the Whippet Fantomas client lib (#284) 2024-10-06 21:22:24 +00:00
Patrick Stevens
5319a33b7b Move a useful function (#283) 2024-10-06 21:15:41 +00:00
Patrick Stevens
29b93b2f20 Pull in AST-manipulating function from Myriad (#281) 2024-10-06 21:08:32 +00:00
Patrick Stevens
40106d8aa3 Use WoofWare.Whippet.Fantomas rather than Myriad.Core (#280) 2024-10-06 20:22:06 +00:00
patrick-conscriptus[bot]
4d641b0662 Automated commit (#279)
Co-authored-by: patrick-conscriptus[bot] <175414948+patrick-conscriptus[bot]@users.noreply.github.com>
2024-10-06 01:23:42 +00:00
66 changed files with 769 additions and 2992 deletions

View File

@@ -3,13 +3,13 @@
"isRoot": true,
"tools": {
"fantomas": {
"version": "6.3.15",
"version": "7.0.1",
"commands": [
"fantomas"
]
},
"fsharp-analyzers": {
"version": "0.27.0",
"version": "0.30.0",
"commands": [
"fsharp-analyzers"
]

View File

@@ -29,7 +29,7 @@ jobs:
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -50,7 +50,7 @@ jobs:
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -67,7 +67,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -82,7 +82,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -97,7 +97,7 @@ jobs:
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -116,7 +116,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -129,7 +129,7 @@ jobs:
steps:
- uses: actions/checkout@master
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -142,7 +142,7 @@ jobs:
steps:
- uses: actions/checkout@master
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -156,7 +156,7 @@ jobs:
with:
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -198,27 +198,40 @@ jobs:
# Verify that there is exactly one nupkg in the artifact that would be NuGet published
run: if [[ $(find packed-attribute -maxdepth 1 -name 'WoofWare.Myriad.Plugins.Attributes.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi
github-release-plugin-dry-run:
needs: [nuget-pack]
github-release-dry-run:
strategy:
matrix:
artifact:
- nuget-package-plugin
- nuget-package-attribute
runs-on: ubuntu-latest
needs: [nuget-pack]
steps:
- uses: actions/checkout@v4
- name: Download NuGet artifact (plugin)
- name: Download NuGet artifact
uses: actions/download-artifact@v4
with:
name: nuget-package-plugin
- name: Download NuGet artifact (attribute)
uses: actions/download-artifact@v4
with:
name: nuget-package-attribute
- name: Tag and release plugin
name: ${{ matrix.artifact }}
- name: Compute package path
id: compute-path
run: |
find . -maxdepth 1 -type f -name 'WoofWare.Myriad.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
- name: Compute tag name
id: compute-tag
env:
DRY_RUN: 1
GITHUB_TOKEN: mock-token
run: sh .github/workflows/tag.sh
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
- name: Tag and release
uses: G-Research/common-actions/github-release@19d7281a0f9f83e13c78f99a610dbc80fc59ba3b
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target-commitish: ${{ github.sha }}
tag: ${{ steps.compute-tag.outputs.output }}
binary-contents: ${{ steps.compute-path.outputs.output }}
dry-run: true
all-required-checks-complete:
needs: [check-dotnet-format, check-nix-format, check-accurate-generations, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack, github-release-plugin-dry-run]
needs: [check-dotnet-format, check-nix-format, check-accurate-generations, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack, github-release-dry-run]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
@@ -241,7 +254,7 @@ jobs:
name: nuget-package-attribute
path: packed
- name: Attest Build Provenance
uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3
uses: actions/attest-build-provenance@c074443f1aee8d4aeeae555aebba3282517141b2 # v2.2.3
with:
subject-path: "packed/*.nupkg"
@@ -260,7 +273,7 @@ jobs:
name: nuget-package-plugin
path: packed
- name: Attest Build Provenance
uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3
uses: actions/attest-build-provenance@c074443f1aee8d4aeeae555aebba3282517141b2 # v2.2.3
with:
subject-path: "packed/*.nupkg"
@@ -276,7 +289,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -309,7 +322,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v29
uses: cachix/install-nix-action@v31
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
@@ -330,7 +343,12 @@ jobs:
nupkg-dir: packed/
dotnet: ${{ steps.dotnet-identify.outputs.dotnet }}
github-release-plugin:
github-release:
strategy:
matrix:
artifact:
- nuget-package-attribute
- nuget-package-plugin
runs-on: ubuntu-latest
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
needs: [all-required-checks-complete]
@@ -339,15 +357,23 @@ jobs:
contents: write
steps:
- uses: actions/checkout@v4
- name: Download NuGet artifact (plugin)
- name: Download NuGet artifact
uses: actions/download-artifact@v4
with:
name: nuget-package-plugin
- name: Download NuGet artifact (attribute)
uses: actions/download-artifact@v4
with:
name: nuget-package-attribute
- name: Tag and release plugin
name: ${{ matrix.artifact }}
- name: Compute package path
id: compute-path
run: |
find . -maxdepth 1 -type f -name 'WoofWare.Myriad.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
- name: Compute tag name
id: compute-tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: sh .github/workflows/tag.sh
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
- name: Tag and release
uses: G-Research/common-actions/github-release@19d7281a0f9f83e13c78f99a610dbc80fc59ba3b
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target-commitish: ${{ github.sha }}
tag: ${{ steps.compute-tag.outputs.output }}
binary-contents: ${{ steps.compute-path.outputs.output }}

View File

@@ -21,20 +21,20 @@ jobs:
- name: Update Nix flake
run: 'nix flake update'
- name: Build passthru
run: 'nix build ".#default.passthru.fetch-deps"'
- name: Build fetch-deps
run: 'nix build ".#default.fetch-deps"'
- name: Run passthru
- name: Run fetch-deps
run: |
set -o pipefail
./result nix/deps.nix
./result nix/deps.json
- name: Format
run: 'nix develop --command alejandra .'
- name: Create token
id: generate-token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v2
with:
# https://github.com/actions/create-github-app-token/issues/136
app-id: ${{ secrets.APP_ID }}

View File

@@ -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

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<IsPackable>false</IsPackable>
<OtherFlags>--reflectionfree $(OtherFlags)</OtherFlags>
</PropertyGroup>

View File

@@ -26769,8 +26769,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"admin/cron/{task}"
.Replace ("{task}", task.ToString () |> System.Uri.EscapeDataString),
"admin/cron/{task}".Replace ("{task}", task.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -26902,8 +26901,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"admin/hooks/{id}"
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
"admin/hooks/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -26945,8 +26943,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"admin/hooks/{id}"
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
"admin/hooks/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -27584,8 +27581,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"amdin/hooks/{id}"
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
"amdin/hooks/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -28008,8 +28004,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"org/{org}/repos"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
"org/{org}/repos".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -28292,8 +28287,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
("orgs/{org}/hooks"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
("orgs/{org}/hooks".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
+ (if "orgs/{org}/hooks".IndexOf (char 63) >= 0 then
"&"
else
@@ -28345,8 +28339,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"orgs/{org}/hooks"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
"orgs/{org}/hooks".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -28538,8 +28531,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
("orgs/{org}/labels"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
("orgs/{org}/labels".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
+ (if "orgs/{org}/labels".IndexOf (char 63) >= 0 then
"&"
else
@@ -28591,8 +28583,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"orgs/{org}/labels"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
"orgs/{org}/labels".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -28784,8 +28775,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
("orgs/{org}/members"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
("orgs/{org}/members".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
+ (if "orgs/{org}/members".IndexOf (char 63) >= 0 then
"&"
else
@@ -29086,8 +29076,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
("orgs/{org}/repos"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
("orgs/{org}/repos".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
+ (if "orgs/{org}/repos".IndexOf (char 63) >= 0 then
"&"
else
@@ -29142,8 +29131,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"orgs/{org}/repos"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
"orgs/{org}/repos".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -29197,8 +29185,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
("orgs/{org}/teams"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
("orgs/{org}/teams".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString)
+ (if "orgs/{org}/teams".IndexOf (char 63) >= 0 then
"&"
else
@@ -29250,8 +29237,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"orgs/{org}/teams"
.Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
"orgs/{org}/teams".Replace ("{org}", org.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -39381,8 +39367,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"repositories/{id}"
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
"repositories/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)
@@ -39745,8 +39730,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
("teams/{id}/members"
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
("teams/{id}/members".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
+ (if "teams/{id}/members".IndexOf (char 63) >= 0 then
"&"
else
@@ -39918,8 +39902,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
("teams/{id}/repos"
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
("teams/{id}/repos".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString)
+ (if "teams/{id}/repos".IndexOf (char 63) >= 0 then
"&"
else
@@ -40807,8 +40790,7 @@ module Gitea =
System.Uri ("/api/v1/", System.UriKind.Relative)
),
System.Uri (
"user/gpg_keys/{id}"
.Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
"user/gpg_keys/{id}".Replace ("{id}", id.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)

View File

@@ -206,3 +206,34 @@ type internal TypeWithInterfaceMock =
interface System.IDisposable with
member this.Dispose () : unit = this.Dispose ()
namespace SomeNamespace
open System
open WoofWare.Myriad.Plugins
/// Mock record type for an interface
type internal TypeWithPropertiesMock =
{
/// Implementation of IDisposable.Dispose
Dispose : unit -> unit
Prop1 : unit -> int
Prop2 : unit -> unit Async
Mem1 : string option -> string[] Async
}
/// An implementation where every method throws.
static member Empty : TypeWithPropertiesMock =
{
Dispose = (fun () -> ())
Prop1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop1"))
Prop2 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Prop2"))
Mem1 = (fun _ -> raise (System.NotImplementedException "Unimplemented mock function: Mem1"))
}
interface TypeWithProperties with
member this.Mem1 arg_0_0 = this.Mem1 (arg_0_0)
member this.Prop1 = this.Prop1 ()
member this.Prop2 = this.Prop2 ()
interface System.IDisposable with
member this.Dispose () : unit = this.Dispose ()

View File

@@ -160,8 +160,7 @@ module PureGymApi =
| null -> System.Uri "https://whatnot.com/"
| v -> v),
System.Uri (
"v1/gyms/{gym}"
.Replace ("{gym}", gym.ToString () |> System.Uri.EscapeDataString),
"v1/gyms/{gym}".Replace ("{gym}", gym.ToString () |> System.Uri.EscapeDataString),
System.UriKind.Relative
)
)

View File

@@ -48,3 +48,10 @@ type TypeWithInterface =
inherit IDisposable
abstract Mem1 : string option -> string[] Async
abstract Mem2 : unit -> string[] Async
[<GenerateMock>]
type TypeWithProperties =
inherit IDisposable
abstract Mem1 : string option -> string[] Async
abstract Prop1 : int
abstract Prop2 : unit Async

View File

@@ -10,7 +10,7 @@
<WarnOn>FS3388,FS3559</WarnOn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.143" PrivateAssets="all"/>
<PackageReference Include="Nerdbank.GitVersioning" Version="3.8.38-alpha" PrivateAssets="all"/>
<SourceLinkGitHubHost Include="github.com" ContentUrl="https://raw.githubusercontent.com"/>
</ItemGroup>
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">

View File

@@ -26,6 +26,11 @@ type ArgParserAttribute (isExtensionMethod : bool) =
/// an argument which looks like a flag but which we don't recognise.)
/// We will still interpret `--help` as requesting help, unless it comes after
/// a standalone `--` separator.
///
/// If the type of the PositionalArgs field is `Choice<'a, 'a>`, then we will
/// tell you whether each arg came before or after a standalone `--` separator.
/// For example, `MyApp foo bar -- baz` with PositionalArgs of `Choice<string, string>`
/// would yield `Choice1Of2 foo, Choice1Of2 bar, Choice2Of2 baz`.
type PositionalArgsAttribute (includeFlagLike : bool) =
inherit Attribute ()

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
@@ -17,10 +17,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ApiSurface" Version="4.1.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1"/>
<PackageReference Include="NUnit" Version="4.2.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
<PackageReference Include="ApiSurface" Version="4.1.20" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0"/>
<PackageReference Include="NUnit" Version="4.3.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"/>
</ItemGroup>
<ItemGroup>

View File

@@ -3,7 +3,7 @@ namespace WoofWare.Myriad.Plugins.Test
open System
open System.Collections.Generic
open System.Text.Json.Nodes
open FsCheck.Random
open FsCheck.FSharp
open Microsoft.FSharp.Reflection
open NUnit.Framework
open FsCheck
@@ -15,21 +15,21 @@ module TestJsonSerde =
let uriGen : Gen<Uri> =
gen {
let! suffix = Arb.generate<int>
let! suffix = ArbMap.generate<int> ArbMap.defaults
return Uri $"https://example.com/%i{suffix}"
}
let rec innerGen (count : int) : Gen<InnerTypeWithBoth> =
gen {
let! guid = Arb.generate<Guid>
let! mapKeys = Gen.listOf Arb.generate<NonNull<string>>
let! guid = ArbMap.generate<Guid> ArbMap.defaults
let! mapKeys = Gen.listOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
let mapKeys = mapKeys |> List.map _.Get |> List.distinct
let! mapValues = Gen.listOfLength mapKeys.Length uriGen
let map = List.zip mapKeys mapValues |> Map.ofList
let! concreteDictKeys =
if count > 0 then
Gen.listOf Arb.generate<NonNull<string>>
Gen.listOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
else
Gen.constant []
@@ -50,13 +50,16 @@ module TestJsonSerde =
|> List.map KeyValuePair
|> Dictionary
let! readOnlyDictKeys = Gen.listOf Arb.generate<NonNull<string>>
let! readOnlyDictKeys = Gen.listOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
let readOnlyDictKeys = readOnlyDictKeys |> List.map _.Get |> List.distinct
let! readOnlyDictValues = Gen.listOfLength readOnlyDictKeys.Length (Gen.listOf Arb.generate<char>)
let! readOnlyDictValues =
Gen.listOfLength readOnlyDictKeys.Length (Gen.listOf (ArbMap.generate<char> ArbMap.defaults))
let readOnlyDict = List.zip readOnlyDictKeys readOnlyDictValues |> readOnlyDict
let! dictKeys = Gen.listOf uriGen
let! dictValues = Gen.listOfLength dictKeys.Length Arb.generate<bool>
let! dictValues = Gen.listOfLength dictKeys.Length (ArbMap.generate<bool> ArbMap.defaults)
let dict = List.zip dictKeys dictValues |> dict
return
@@ -71,28 +74,38 @@ module TestJsonSerde =
let outerGen : Gen<JsonRecordTypeWithBoth> =
gen {
let! a = Arb.generate<int>
let! b = Arb.generate<NonNull<string>>
let! c = Gen.listOf Arb.generate<int>
let! a = ArbMap.generate<int> ArbMap.defaults
let! b = ArbMap.generate<NonNull<string>> ArbMap.defaults
let! c = Gen.listOf (ArbMap.generate<int> ArbMap.defaults)
let! depth = Gen.choose (0, 2)
let! d = innerGen depth
let! e = Gen.arrayOf Arb.generate<NonNull<string>>
let! arr = Gen.arrayOf Arb.generate<int>
let! byte = Arb.generate
let! sbyte = Arb.generate
let! i = Arb.generate
let! i32 = Arb.generate
let! i64 = Arb.generate
let! u = Arb.generate
let! u32 = Arb.generate
let! u64 = Arb.generate
let! f = Arb.generate |> Gen.filter (fun s -> Double.IsFinite (s / 1.0<measure>))
let! f32 = Arb.generate |> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
let! single = Arb.generate |> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
let! intMeasureOption = Arb.generate
let! intMeasureNullable = Arb.generate
let! e = Gen.arrayOf (ArbMap.generate<NonNull<string>> ArbMap.defaults)
let! arr = Gen.arrayOf (ArbMap.generate<int> ArbMap.defaults)
let! byte = ArbMap.generate ArbMap.defaults
let! sbyte = ArbMap.generate ArbMap.defaults
let! i = ArbMap.generate ArbMap.defaults
let! i32 = ArbMap.generate ArbMap.defaults
let! i64 = ArbMap.generate ArbMap.defaults
let! u = ArbMap.generate ArbMap.defaults
let! u32 = ArbMap.generate ArbMap.defaults
let! u64 = ArbMap.generate ArbMap.defaults
let! f =
ArbMap.generate ArbMap.defaults
|> Gen.filter (fun s -> Double.IsFinite (s / 1.0<measure>))
let! f32 =
ArbMap.generate ArbMap.defaults
|> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
let! single =
ArbMap.generate ArbMap.defaults
|> Gen.filter (fun s -> Single.IsFinite (s / 1.0f<measure>))
let! intMeasureOption = ArbMap.generate ArbMap.defaults
let! intMeasureNullable = ArbMap.generate ArbMap.defaults
let! someEnum = Gen.choose (0, 1)
let! timestamp = Arb.generate
let! timestamp = ArbMap.generate ArbMap.defaults
return
{
@@ -270,10 +283,10 @@ module TestJsonSerde =
match case with
| 0 -> return FirstDu.EmptyCase
| 1 ->
let! s = Arb.generate<NonNull<string>>
let! s = ArbMap.generate<NonNull<string>> ArbMap.defaults
return FirstDu.Case1 s.Get
| 2 ->
let! i = Arb.generate<int>
let! i = ArbMap.generate<int> ArbMap.defaults
let! record = outerGen
return FirstDu.Case2 (record, i)
| _ -> return failwith $"unexpected: %i{case}"
@@ -293,7 +306,6 @@ module TestJsonSerde =
[<Test>]
let ``DU generator covers all cases`` () =
let rand = Random ()
let cases = FSharpType.GetUnionCases typeof<FirstDu>
let counts = Array.zeroCreate<int> cases.Length
@@ -301,11 +313,13 @@ module TestJsonSerde =
let mutable i = 0
while i < 10_000 && Array.exists (fun i -> i = 0) counts do
let du = Gen.eval 10 (StdGen.StdGen (rand.Next (), rand.Next ())) duGen
let property (du : FirstDu) =
let tag = decompose du
counts.[tag] <- counts.[tag] + 1
i <- i + 1
true
Check.One (Config.Quick, Prop.forAll (Arb.fromGen duGen) property)
for i in counts do
i |> shouldBeGreaterThan 0

View File

@@ -34,3 +34,16 @@ module TestMockGenerator =
mock.Mem1 3 'a' |> shouldEqual "aaa"
mock.Mem2 (3, "hi") 'a' |> shouldEqual "hiahiahi"
mock.Mem3 (3, "hi") 'a' |> shouldEqual "hiahiahi"
[<Test>]
let ``Example of use: properties`` () =
let mock : TypeWithProperties =
{ TypeWithPropertiesMock.Empty with
Mem1 = fun i -> async { return Option.toArray i }
Prop1 = fun () -> 44
}
:> _
mock.Mem1 (Some "hi") |> Async.RunSynchronously |> shouldEqual [| "hi" |]
mock.Prop1 |> shouldEqual 44

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<!--
@@ -9,6 +9,7 @@
I have not yet seen a single instance where I care about this warning
-->
<NoWarn>$(NoWarn),NU1903</NoWarn>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
</PropertyGroup>
<ItemGroup>
@@ -41,12 +42,12 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ApiSurface" Version="4.1.5"/>
<PackageReference Include="FsCheck" Version="2.16.6"/>
<PackageReference Include="FsUnit" Version="6.0.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1"/>
<PackageReference Include="NUnit" Version="4.2.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
<PackageReference Include="ApiSurface" Version="4.1.20"/>
<PackageReference Include="FsCheck" Version="3.2.0"/>
<PackageReference Include="FsUnit" Version="7.0.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0"/>
<PackageReference Include="NUnit" Version="4.3.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"/>
</ItemGroup>
<ItemGroup>

View File

@@ -4,6 +4,8 @@ open System
open System.Text
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
open TypeEquality
open WoofWare.Whippet.Fantomas
type internal ArgParserOutputSpec =
{
@@ -671,7 +673,7 @@ module internal ArgParserGenerator =
args
|> Map.toList
|> List.map (fun (ident, expr) -> SynLongIdent.create [ Ident.create ident ], expr)
|> AstHelper.instantiateRecord
|> SynExpr.createRecord None
)
tree, counter
@@ -1756,10 +1758,7 @@ type ArgParserGenerator () =
let ast, _ =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
let types =
Ast.extractTypeDefn ast
|> List.groupBy (fst >> List.map _.idText >> String.concat ".")
|> List.map (fun (_, v) -> fst (List.head v), List.collect snd v)
let types = Ast.getTypes ast
let opens = AstHelper.extractOpens ast

View File

@@ -2,173 +2,7 @@ namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
open Fantomas.FCS.Xml
type internal ParameterInfo =
{
Attributes : SynAttribute list
IsOptional : bool
Id : Ident option
Type : SynType
}
type internal TupledArg =
{
HasParen : bool
Args : ParameterInfo list
}
type internal MemberInfo =
{
ReturnType : SynType
Accessibility : SynAccess option
/// Each element of this list is a list of args in a tuple, or just one arg if not a tuple.
Args : TupledArg list
Identifier : Ident
Attributes : SynAttribute list
XmlDoc : PreXmlDoc option
IsInline : bool
IsMutable : bool
}
[<RequireQualifiedAccess>]
type internal PropertyAccessors =
| Get
| Set
| GetSet
type internal PropertyInfo =
{
Type : SynType
Accessibility : SynAccess option
Attributes : SynAttribute list
XmlDoc : PreXmlDoc option
Accessors : PropertyAccessors
IsInline : bool
Identifier : Ident
}
type internal InterfaceType =
{
Attributes : SynAttribute list
Name : LongIdent
Inherits : SynType list
Members : MemberInfo list
Properties : PropertyInfo list
Generics : SynTyparDecls option
Accessibility : SynAccess option
}
type internal RecordType =
{
Name : Ident
Fields : SynField list
/// Any additional members which are not record fields.
Members : SynMemberDefns option
XmlDoc : PreXmlDoc option
Generics : SynTyparDecls option
TypeAccessibility : SynAccess option
ImplAccessibility : SynAccess option
Attributes : SynAttribute list
}
/// Parse from the AST.
static member OfRecord
(sci : SynComponentInfo)
(smd : SynMemberDefns)
(access : SynAccess option)
(recordFields : SynField list)
: RecordType
=
match sci with
| SynComponentInfo.SynComponentInfo (attrs, typars, _, longId, doc, _, implAccess, _) ->
{
Name = List.last longId
Fields = recordFields
Members = if smd.IsEmpty then None else Some smd
XmlDoc = if doc.IsEmpty then None else Some doc
Generics = typars
ImplAccessibility = implAccess
TypeAccessibility = access
Attributes = attrs |> List.collect (fun l -> l.Attributes)
}
/// Methods for manipulating UnionCase.
[<RequireQualifiedAccess>]
module UnionCase =
/// Construct our structured `UnionCase` from an FCS `SynUnionCase`: extract everything
/// we care about from the AST representation.
let ofSynUnionCase (case : SynUnionCase) : UnionCase<Ident option> =
match case with
| SynUnionCase.SynUnionCase (attributes, ident, caseType, xmlDoc, access, _, _) ->
let ident =
match ident with
| SynIdent.SynIdent (ident, _) -> ident
let fields =
match caseType with
| SynUnionCaseKind.Fields cases -> cases
| SynUnionCaseKind.FullType _ -> failwith "unexpected FullType union"
{
Name = ident
XmlDoc = if xmlDoc.IsEmpty then None else Some xmlDoc
Access = access
Attributes = attributes |> List.collect (fun t -> t.Attributes)
Fields = fields |> List.map SynField.extract
}
/// Functorial `map`.
let mapIdentFields<'a, 'b> (f : 'a -> 'b) (unionCase : UnionCase<'a>) : UnionCase<'b> =
{
Attributes = unionCase.Attributes
Name = unionCase.Name
Access = unionCase.Access
XmlDoc = unionCase.XmlDoc
Fields = unionCase.Fields |> List.map (SynField.mapIdent f)
}
/// Everything you need to know about a discriminated union definition.
type internal UnionType =
{
/// The name of the DU: for example, `type Foo = | Blah` has this being `Foo`.
Name : Ident
/// Any additional members which are not union cases.
Members : SynMemberDefns option
/// Any docstring associated with the DU itself (not its cases).
XmlDoc : PreXmlDoc option
/// Generic type parameters this DU takes: `type Foo<'a> = | ...`.
Generics : SynTyparDecls option
/// Attributes of the DU (not its cases): `[<Attr>] type Foo = | ...`
Attributes : SynAttribute list
/// Accessibility modifier of the DU: `type private Foo = ...`
TypeAccessibility : SynAccess option
/// Accessibility modifier of the DU's implementation: `type Foo = private | ...`
ImplAccessibility : SynAccess option
/// The actual DU cases themselves.
Cases : UnionCase<Ident option> list
}
static member OfUnion
(sci : SynComponentInfo)
(smd : SynMemberDefns)
(access : SynAccess option)
(cases : SynUnionCase list)
: UnionType
=
match sci with
| SynComponentInfo.SynComponentInfo (attrs, typars, _, longId, doc, _, implAccess, _) ->
{
Name = List.last longId
Members = if smd.IsEmpty then None else Some smd
XmlDoc = if doc.IsEmpty then None else Some doc
Generics = typars
Attributes = attrs |> List.collect (fun l -> l.Attributes)
TypeAccessibility = access
ImplAccessibility = implAccess
Cases = cases |> List.map UnionCase.ofSynUnionCase
}
open WoofWare.Whippet.Fantomas
/// Anything that is part of an ADT.
/// A record is a product of stuff; this type represents one of those stuffs.
@@ -202,13 +36,6 @@ module internal AstHelper =
| SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Enum _, _) -> true
| _ -> false
let instantiateRecord (fields : (SynLongIdent * SynExpr) list) : SynExpr =
let fields =
fields
|> List.map (fun (rfn, synExpr) -> SynExprRecordField ((rfn, true), Some range0, Some synExpr, None))
SynExpr.Record (None, None, fields, range0)
let defineRecordType (record : RecordType) : SynTypeDefn =
let name =
SynComponentInfo.create record.Name

View File

@@ -3,11 +3,11 @@ namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.SyntaxTrivia
open Fantomas.FCS.Xml
open WoofWare.Whippet.Fantomas
[<RequireQualifiedAccess>]
module internal CataGenerator =
open Fantomas.FCS.Text.Range
open Myriad.Core.Ast
/// The user-provided DU contains cases, each of which contains fields.
/// We have a hard-coded set of things we know how to deal with as field contents.
@@ -174,20 +174,14 @@ module internal CataGenerator =
|> SynExpr.applyFunction (SynExpr.createLongIdent [ "Seq" ; "exactlyOne" ])
|> SynExpr.createLet
[
SynBinding.Let (
valData = SynValData.SynValData (None, SynValInfo.empty, None),
pattern =
SynPat.tupleNoParen (
allArtificialTyparNames
|> List.map (fun (t : Ident) ->
SynPat.namedI (Ident.create (t.idText + "Stack") |> Ident.lowerFirstLetter)
)
),
expr =
SynExpr.applyFunction
(SynExpr.applyFunction (SynExpr.createIdent "loop") (SynExpr.createIdent "cata"))
(SynExpr.createIdent "instructions")
)
SynBinding.basicTuple
(allArtificialTyparNames
|> List.map (fun (t : Ident) ->
SynPat.namedI (Ident.create (t.idText + "Stack") |> Ident.lowerFirstLetter)
))
(SynExpr.applyFunction
(SynExpr.applyFunction (SynExpr.createIdent "loop") (SynExpr.createIdent "cata"))
(SynExpr.createIdent "instructions"))
]
]
|> SynExpr.sequential
@@ -1180,6 +1174,29 @@ module internal CataGenerator =
]
|> SynModuleOrNamespace.createNamespace ns
/// This function comes from Myriad, and is therefore derived from an Apache 2.0-licenced work.
/// https://github.com/MoiraeSoftware/myriad/blob/3c9818faabf9d508c10c28d5ecd26e66fafb48a1/src/Myriad.Core/Ast.fs#L160
/// A copy of the Apache 2.0 licence is at ApacheLicence.txt.
let groupedTypeDefns (ast : ParsedInput) : (LongIdent * SynTypeDefn list) list =
let rec extractTypes (moduleDecls : SynModuleDecl list) (ns : LongIdent) =
[
for moduleDecl in moduleDecls do
match moduleDecl with
| SynModuleDecl.Types (types, _) -> yield (ns, types)
| SynModuleDecl.NestedModule (SynComponentInfo (_, _, _, longId, _, _, _, _), _, decls, _, _, _) ->
let combined = longId |> List.append ns
yield! (extractTypes decls combined)
| _ -> ()
]
[
match ast with
| ParsedInput.ImplFile (ParsedImplFileInput (_, _, _, _, _, modules, _, _, _)) ->
for SynModuleOrNamespace (namespaceId, _, _, moduleDecls, _, _, _, _, _) in modules do
yield! extractTypes moduleDecls namespaceId
| _ -> ()
]
open Myriad.Core
/// Myriad generator that provides a catamorphism for an algebraic data type.
@@ -1193,7 +1210,7 @@ type CreateCatamorphismGenerator () =
let ast, _ =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
let types = Ast.extractTypeDefn ast
let types = CataGenerator.groupedTypeDefns ast
let opens = AstHelper.extractOpens ast

View File

@@ -3,6 +3,7 @@ namespace WoofWare.Myriad.Plugins
open System.IO
open System.Net.Http
open Fantomas.FCS.Syntax
open WoofWare.Whippet.Fantomas
type internal HttpClientGeneratorOutputSpec =
{
@@ -643,7 +644,7 @@ module internal HttpClientGenerator =
yield jsonNode
| String -> yield responseString
| Stream -> yield responseStream
| Unit ->
| UnitType ->
// What we're returning doesn't depend on the content, so don't bother!
()
| _ ->
@@ -995,7 +996,7 @@ type HttpClientGenerator () =
let ast, _ =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
let types = Ast.extractTypeDefn ast
let types = Ast.getTypes ast
let opens = AstHelper.extractOpens ast

View File

@@ -3,6 +3,7 @@ namespace WoofWare.Myriad.Plugins
open System
open Fantomas.FCS.Syntax
open Fantomas.FCS.Xml
open WoofWare.Whippet.Fantomas
type internal GenerateMockOutputSpec =
{
@@ -88,7 +89,7 @@ module internal InterfaceMockGenerator =
[]
else
[ SynPat.unit ])
(AstHelper.instantiateRecord constructorFields)
(SynExpr.createRecord None constructorFields)
|> SynBinding.withXmlDoc (PreXmlDoc.create "An implementation where every method throws.")
|> SynBinding.withReturnAnnotation constructorReturnType
|> SynMemberDefn.staticMember
@@ -158,6 +159,15 @@ module internal InterfaceMockGenerator =
|> SynMemberDefn.memberImplementation
)
let properties =
interfaceType.Properties
|> List.map (fun pi ->
SynExpr.createLongIdent' [ Ident.create "this" ; pi.Identifier ]
|> SynExpr.applyTo (SynExpr.CreateConst ())
|> SynBinding.basic [ Ident.create "this" ; pi.Identifier ] []
|> SynMemberDefn.memberImplementation
)
let interfaceName =
let baseName = SynType.createLongIdent interfaceType.Name
@@ -173,7 +183,7 @@ module internal InterfaceMockGenerator =
SynType.app' baseName generics
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
SynMemberDefn.Interface (interfaceName, Some range0, Some (members @ properties), range0)
let access =
match interfaceType.Accessibility, spec.IsInternal with
@@ -247,6 +257,15 @@ module internal InterfaceMockGenerator =
|> SynField.make
|> SynField.withDocString (mem.XmlDoc |> Option.defaultValue PreXmlDoc.Empty)
let constructProperty (prop : PropertyInfo) : SynField =
{
Attrs = []
Ident = Some prop.Identifier
Type = SynType.toFun [ SynType.unit ] prop.Type
}
|> SynField.make
|> SynField.withDocString (prop.XmlDoc |> Option.defaultValue PreXmlDoc.Empty)
let createRecord
(namespaceId : LongIdent)
(opens : SynOpenDeclTarget list)
@@ -254,7 +273,12 @@ module internal InterfaceMockGenerator =
: SynModuleOrNamespace
=
let interfaceType = AstHelper.parseInterface interfaceType
let fields = interfaceType.Members |> List.map constructMember
let fields =
interfaceType.Members
|> List.map constructMember
|> List.append (interfaceType.Properties |> List.map constructProperty)
let docString = PreXmlDoc.create "Mock record type for an interface"
let name =
@@ -290,14 +314,14 @@ type InterfaceMockGenerator () =
let ast, _ =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
let types = Ast.extractTypeDefn ast
let types = Ast.getTypes ast
let namespaceAndInterfaces =
types
|> List.choose (fun (ns, types) ->
types
|> List.choose (fun typeDef ->
match Ast.getAttribute<GenerateMockAttribute> typeDef with
match SynTypeDefn.getAttribute typeof<GenerateMockAttribute>.Name typeDef with
| None ->
let name = SynTypeDefn.getName typeDef |> List.map _.idText |> String.concat "."

View File

@@ -4,6 +4,7 @@ open System
open System.Text
open Fantomas.FCS.Syntax
open Fantomas.FCS.SyntaxTrivia
open WoofWare.Whippet.Fantomas
type internal JsonParseOutputSpec =
{
@@ -280,7 +281,7 @@ module internal JsonParseGenerator =
parseNumberType options propertyName node primType
|> SynExpr.pipeThroughFunction (Measure.getLanguagePrimitivesMeasure primType)
| JsonNode -> node
| Unit -> SynExpr.CreateConst ()
| UnitType -> SynExpr.CreateConst ()
| _ ->
// Let's just hope that we've also got our own type annotation!
let typeName =
@@ -350,10 +351,7 @@ module internal JsonParseGenerator =
let getParseOptions (fieldAttrs : SynAttribute list) =
(JsonParseOption.None, fieldAttrs)
||> List.fold (fun options attr ->
if
(SynLongIdent.toString attr.TypeName)
.EndsWith ("JsonNumberHandling", StringComparison.Ordinal)
then
if (SynLongIdent.toString attr.TypeName).EndsWith ("JsonNumberHandling", StringComparison.Ordinal) then
let qualifiedEnumValue =
match SynExpr.stripOptionalParen attr.ArgExpr with
| SynExpr.LongIdent (_, SynLongIdent (ident, _, _), _, _) when isJsonNumberHandling ident ->
@@ -383,15 +381,13 @@ module internal JsonParseGenerator =
let propertyNameAttr =
fieldData.Attrs
|> List.tryFind (fun attr ->
(SynLongIdent.toString attr.TypeName)
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonPropertyName", StringComparison.Ordinal)
)
let extensionDataAttr =
fieldData.Attrs
|> List.tryFind (fun attr ->
(SynLongIdent.toString attr.TypeName)
.EndsWith ("JsonExtensionData", StringComparison.Ordinal)
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonExtensionData", StringComparison.Ordinal)
)
let propertyName =
@@ -484,7 +480,7 @@ module internal JsonParseGenerator =
let finalConstruction =
fields
|> List.mapi (fun i fieldData -> SynLongIdent.createI fieldData.Ident, SynExpr.createIdent $"arg_%i{i}")
|> AstHelper.instantiateRecord
|> SynExpr.createRecord None
(finalConstruction, assignments)
||> List.fold (fun final assignment -> SynExpr.createLet [ assignment ] final)
@@ -710,13 +706,13 @@ type JsonParseGenerator () =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
let relevantTypes =
Ast.extractTypeDefn ast
Ast.getTypes 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
elif AstHelper.isEnum defn then Some defn
if SynTypeDefn.isRecord defn then Some defn
elif SynTypeDefn.isDu defn then Some defn
elif SynTypeDefn.isEnum defn then Some defn
else None
)
|> fun defns -> name, defns

View File

@@ -3,6 +3,7 @@ namespace WoofWare.Myriad.Plugins
open System
open System.Text
open Fantomas.FCS.Syntax
open WoofWare.Whippet.Fantomas
type internal JsonSerializeOutputSpec =
{
@@ -147,7 +148,7 @@ module internal JsonSerializeGenerator =
|> SynExpr.createLambda "field"
|> fun e -> e, false
| JsonNode -> SynExpr.createIdent "id", true
| Unit ->
| UnitType ->
SynExpr.createLambda
"value"
(SynExpr.createLongIdent [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonObject" ]
@@ -179,8 +180,7 @@ module internal JsonSerializeGenerator =
let propertyNameAttr =
attrs
|> List.tryFind (fun attr ->
(SynLongIdent.toString attr.TypeName)
.EndsWith ("JsonPropertyName", StringComparison.Ordinal)
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonPropertyName", StringComparison.Ordinal)
)
match propertyNameAttr with
@@ -197,8 +197,7 @@ module internal JsonSerializeGenerator =
let getIsJsonExtension (attrs : SynAttribute list) : bool =
attrs
|> List.tryFind (fun attr ->
(SynLongIdent.toString attr.TypeName)
.EndsWith ("JsonExtensionData", StringComparison.Ordinal)
(SynLongIdent.toString attr.TypeName).EndsWith ("JsonExtensionData", StringComparison.Ordinal)
)
|> Option.isSome
@@ -527,13 +526,13 @@ type JsonSerializeGenerator () =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
let relevantTypes =
Ast.extractTypeDefn ast
Ast.getTypes 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
elif AstHelper.isEnum defn then Some defn
if SynTypeDefn.isRecord defn then Some defn
elif SynTypeDefn.isDu defn then Some defn
elif SynTypeDefn.isEnum defn then Some defn
else None
)
|> fun defns -> name, defns

View File

@@ -1,6 +1,7 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open WoofWare.Whippet.Fantomas
[<RequireQualifiedAccess>]
module internal Measure =
@@ -20,5 +21,4 @@ module internal Measure =
| l ->
let l = String.concat "." l
failwith $"unrecognised type for measure: %s{l}"
|> SynExpr.createLongIdent

View File

@@ -2,28 +2,6 @@ namespace WoofWare.Myriad.Plugins
open System.Collections.Generic
type internal DesiredGenerator =
| InterfaceMock of isInternal : bool option
| JsonParse of extensionMethod : bool option
| JsonSerialize of extensionMethod : bool option
| HttpClient of extensionMethod : bool option
static member Parse (s : string) =
match s with
| "GenerateMock" -> DesiredGenerator.InterfaceMock None
| "GenerateMock(true)" -> DesiredGenerator.InterfaceMock (Some true)
| "GenerateMock(false)" -> DesiredGenerator.InterfaceMock (Some false)
| "JsonParse" -> DesiredGenerator.JsonParse None
| "JsonParse(true)" -> DesiredGenerator.JsonParse (Some true)
| "JsonParse(false)" -> DesiredGenerator.JsonParse (Some false)
| "JsonSerialize" -> DesiredGenerator.JsonSerialize None
| "JsonSerialize(true)" -> DesiredGenerator.JsonSerialize (Some true)
| "JsonSerialize(false)" -> DesiredGenerator.JsonSerialize (Some false)
| "HttpClient" -> DesiredGenerator.HttpClient None
| "HttpClient(true)" -> DesiredGenerator.HttpClient (Some true)
| "HttpClient(false)" -> DesiredGenerator.HttpClient (Some false)
| _ -> failwith $"Failed to parse as a generator specification: %s{s}"
[<RequireQualifiedAccess>]
module internal MyriadParamParser =
(*

View File

@@ -0,0 +1,23 @@
namespace WoofWare.Myriad.Plugins
type internal DesiredGenerator =
| InterfaceMock of isInternal : bool option
| JsonParse of extensionMethod : bool option
| JsonSerialize of extensionMethod : bool option
| HttpClient of extensionMethod : bool option
static member Parse (s : string) =
match s with
| "GenerateMock" -> DesiredGenerator.InterfaceMock None
| "GenerateMock(true)" -> DesiredGenerator.InterfaceMock (Some true)
| "GenerateMock(false)" -> DesiredGenerator.InterfaceMock (Some false)
| "JsonParse" -> DesiredGenerator.JsonParse None
| "JsonParse(true)" -> DesiredGenerator.JsonParse (Some true)
| "JsonParse(false)" -> DesiredGenerator.JsonParse (Some false)
| "JsonSerialize" -> DesiredGenerator.JsonSerialize None
| "JsonSerialize(true)" -> DesiredGenerator.JsonSerialize (Some true)
| "JsonSerialize(false)" -> DesiredGenerator.JsonSerialize (Some false)
| "HttpClient" -> DesiredGenerator.HttpClient None
| "HttpClient(true)" -> DesiredGenerator.HttpClient (Some true)
| "HttpClient(false)" -> DesiredGenerator.HttpClient (Some false)
| _ -> failwith $"Failed to parse as a generator specification: %s{s}"

View File

@@ -1,32 +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
| "string" -> [ "System" ; "String" ] |> Some
| "bool" -> [ "System" ; "Boolean" ] |> Some
| _ -> None
|> Option.map (List.map (fun i -> (Ident (i, range0))))

View File

@@ -1,7 +1,9 @@
namespace WoofWare.Myriad.Plugins
open System
open Fantomas.FCS.Syntax
open Fantomas.FCS.Xml
open WoofWare.Whippet.Fantomas
[<RequireQualifiedAccess>]
module internal RemoveOptionsGenerator =
@@ -58,7 +60,7 @@ module internal RemoveOptionsGenerator =
Attributes = []
}
let typeDecl = AstHelper.defineRecordType record
let typeDecl = RecordType.ToAst record
SynModuleDecl.Types ([ typeDecl ], range0)
@@ -95,7 +97,7 @@ module internal RemoveOptionsGenerator =
SynLongIdent.createI fieldData.Ident, body
)
|> AstHelper.instantiateRecord
|> SynExpr.createRecord None
SynBinding.basic
[ functionName ]
@@ -145,44 +147,31 @@ type RemoveOptionsGenerator () =
let ast, _ =
Ast.fromFilename context.InputFilename |> Async.RunSynchronously |> Array.head
let records = Ast.extractRecords ast
let records = Ast.getRecords ast
let namespaceAndRecords =
records
|> List.choose (fun (ns, types) ->
match
types
|> List.filter (SynTypeDefn.hasAttribute typeof<RemoveOptionsAttribute>.Name)
with
| [] -> None
| types ->
let types =
types
|> List.map (fun ty ->
match ty with
| SynTypeDefn.SynTypeDefn (sci,
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (access,
fields,
_),
_),
smd,
smdo,
_,
_) -> RecordType.OfRecord sci smd access fields
| _ -> failwith "unexpectedly not a record"
)
Some (ns, types)
|> List.collect (fun (ns, ty) ->
ty
|> List.filter (fun record ->
record.Attributes
|> List.exists (fun attr ->
attr.TypeName.LongIdent
|> List.last
|> _.idText
|> fun s ->
if s.EndsWith ("Attribute", StringComparison.Ordinal) then
s
else
$"%s{s}Attribute"
|> (=) typeof<RemoveOptionsAttribute>.Name
)
)
|> List.map (fun ty -> ns, ty)
)
let modules =
namespaceAndRecords
|> List.collect (fun (ns, records) ->
records
|> List.map (fun record ->
let recordModule = RemoveOptionsGenerator.createRecordModule ns record
recordModule
)
)
|> List.map (fun (ns, record) -> RemoveOptionsGenerator.createRecordModule ns record)
Output.Ast modules

View File

@@ -292,27 +292,4 @@ WoofWare.Myriad.Plugins.SwaggerParameter.In [property]: [read-only] WoofWare.Myr
WoofWare.Myriad.Plugins.SwaggerParameter.Name [property]: [read-only] string
WoofWare.Myriad.Plugins.SwaggerParameter.Parse [static method]: System.Text.Json.Nodes.JsonObject -> WoofWare.Myriad.Plugins.SwaggerParameter
WoofWare.Myriad.Plugins.SwaggerParameter.Required [property]: [read-only] bool option
WoofWare.Myriad.Plugins.SwaggerParameter.Type [property]: [read-only] WoofWare.Myriad.Plugins.Definition
WoofWare.Myriad.Plugins.SynFieldData`1 inherit obj
WoofWare.Myriad.Plugins.SynFieldData`1..ctor [constructor]: (Fantomas.FCS.Syntax.SynAttribute list, 'Ident, Fantomas.FCS.Syntax.SynType)
WoofWare.Myriad.Plugins.SynFieldData`1.Attrs [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list
WoofWare.Myriad.Plugins.SynFieldData`1.get_Attrs [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list
WoofWare.Myriad.Plugins.SynFieldData`1.get_Ident [method]: unit -> 'Ident
WoofWare.Myriad.Plugins.SynFieldData`1.get_Type [method]: unit -> Fantomas.FCS.Syntax.SynType
WoofWare.Myriad.Plugins.SynFieldData`1.Ident [property]: [read-only] 'Ident
WoofWare.Myriad.Plugins.SynFieldData`1.Type [property]: [read-only] Fantomas.FCS.Syntax.SynType
WoofWare.Myriad.Plugins.UnionCase inherit obj
WoofWare.Myriad.Plugins.UnionCase.mapIdentFields [static method]: ('a -> 'b) -> 'a WoofWare.Myriad.Plugins.UnionCase -> 'b WoofWare.Myriad.Plugins.UnionCase
WoofWare.Myriad.Plugins.UnionCase.ofSynUnionCase [static method]: Fantomas.FCS.Syntax.SynUnionCase -> Fantomas.FCS.Syntax.Ident option WoofWare.Myriad.Plugins.UnionCase
WoofWare.Myriad.Plugins.UnionCase`1 inherit obj
WoofWare.Myriad.Plugins.UnionCase`1..ctor [constructor]: (Fantomas.FCS.Syntax.Ident, Fantomas.FCS.Xml.PreXmlDoc option, Fantomas.FCS.Syntax.SynAccess option, Fantomas.FCS.Syntax.SynAttribute list, 'ident WoofWare.Myriad.Plugins.SynFieldData list)
WoofWare.Myriad.Plugins.UnionCase`1.Access [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option
WoofWare.Myriad.Plugins.UnionCase`1.Attributes [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list
WoofWare.Myriad.Plugins.UnionCase`1.Fields [property]: [read-only] 'ident WoofWare.Myriad.Plugins.SynFieldData list
WoofWare.Myriad.Plugins.UnionCase`1.get_Access [method]: unit -> Fantomas.FCS.Syntax.SynAccess option
WoofWare.Myriad.Plugins.UnionCase`1.get_Attributes [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list
WoofWare.Myriad.Plugins.UnionCase`1.get_Fields [method]: unit -> 'ident WoofWare.Myriad.Plugins.SynFieldData list
WoofWare.Myriad.Plugins.UnionCase`1.get_Name [method]: unit -> Fantomas.FCS.Syntax.Ident
WoofWare.Myriad.Plugins.UnionCase`1.get_XmlDoc [method]: unit -> Fantomas.FCS.Xml.PreXmlDoc option
WoofWare.Myriad.Plugins.UnionCase`1.Name [property]: [read-only] Fantomas.FCS.Syntax.Ident
WoofWare.Myriad.Plugins.UnionCase`1.XmlDoc [property]: [read-only] Fantomas.FCS.Xml.PreXmlDoc option
WoofWare.Myriad.Plugins.SwaggerParameter.Type [property]: [read-only] WoofWare.Myriad.Plugins.Definition

View File

@@ -6,6 +6,7 @@ open System.Threading
open Fantomas.FCS.Syntax
open Fantomas.FCS.Xml
open Fantomas.FCS.Text.Range
open WoofWare.Whippet.Fantomas
type internal SwaggerClientConfig =
{

View File

@@ -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)
}
*)

View File

@@ -1,65 +0,0 @@
namespace WoofWare.Myriad.Plugins
open System
open System.Text
open System.Text.RegularExpressions
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<RequireQualifiedAccess>]
module internal Ident =
let inline create (s : string) = Ident (s, range0)
/// Fantomas bug, perhaps? "type" is not rendered as ``type``, although the ASTs are identical
/// apart from the ranges?
/// Awful hack: here is a function that does this sort of thing.
let createSanitisedParamName (s : string) =
match s with
| "type" -> create "type'"
| "private" -> create "private'"
| _ ->
let result = StringBuilder ()
for i = 0 to s.Length - 1 do
if Char.IsLetter s.[i] then
result.Append s.[i] |> ignore<StringBuilder>
elif Char.IsNumber s.[i] then
if result.Length > 0 then
result.Append s.[i] |> ignore<StringBuilder>
elif s.[i] = '_' || s.[i] = '-' then
result.Append '_' |> ignore<StringBuilder>
else
failwith $"could not convert to ident: %s{s}"
create (result.ToString ())
let private alnum = Regex @"^[a-zA-Z][a-zA-Z0-9]*$"
let createSanitisedTypeName (s : string) =
let result = StringBuilder ()
let mutable capitalize = true
for i = 0 to s.Length - 1 do
if Char.IsLetter s.[i] then
if capitalize then
result.Append (Char.ToUpperInvariant s.[i]) |> ignore<StringBuilder>
capitalize <- false
else
result.Append s.[i] |> ignore<StringBuilder>
elif Char.IsNumber s.[i] then
if result.Length > 0 then
result.Append s.[i] |> ignore<StringBuilder>
elif s.[i] = '_' then
capitalize <- true
if result.Length = 0 then
failwith $"String %s{s} was not suitable as a type identifier"
Ident (result.ToString (), range0)
let lowerFirstLetter (x : Ident) : Ident =
let result = StringBuilder x.idText.Length
result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore
result.Append x.idText.[1..] |> ignore
create ((result : StringBuilder).ToString ())

View File

@@ -1,17 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Xml
open Fantomas.FCS.Text.Range
[<RequireQualifiedAccess>]
module internal PreXmlDoc =
let create (s : string) : PreXmlDoc =
let s = s.Split "\n"
for i = 0 to s.Length - 1 do
s.[i] <- " " + s.[i]
PreXmlDoc.Create (s, range0)
let create' (s : string seq) : PreXmlDoc =
PreXmlDoc.Create (Array.ofSeq s, range0)

View File

@@ -1,7 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
[<RequireQualifiedAccess>]
module internal SynArgInfo =
let empty = SynArgInfo.SynArgInfo ([], false, None)

View File

@@ -1,30 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<RequireQualifiedAccess>]
module internal SynArgPats =
let createNamed (caseNames : string list) : SynArgPats =
match caseNames.Length with
| 0 -> SynArgPats.Pats []
| 1 ->
SynPat.Named (SynIdent.createS caseNames.[0], false, None, range0)
|> List.singleton
|> SynArgPats.Pats
| len ->
caseNames
|> List.map (fun name -> SynPat.Named (SynIdent.createS name, false, None, range0))
|> fun t -> SynPat.Tuple (false, t, List.replicate (len - 1) range0, range0)
|> fun t -> SynPat.Paren (t, range0)
|> List.singleton
|> SynArgPats.Pats
let create (pats : SynPat list) : SynArgPats =
match pats.Length with
| 0 -> SynArgPats.Pats []
| 1 -> [ pats.[0] ] |> SynArgPats.Pats
| len ->
SynPat.Paren (SynPat.Tuple (false, pats, List.replicate (len - 1) range0, range0), range0)
|> List.singleton
|> SynArgPats.Pats

View File

@@ -1,27 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<RequireQualifiedAccess>]
module internal SynAttribute =
let inline create (typeName : SynLongIdent) (arg : SynExpr) : SynAttribute =
{
TypeName = typeName
ArgExpr = arg
Target = None
AppliesToGetterAndSetter = false
Range = range0
}
let internal compilationRepresentation : SynAttribute =
[ "CompilationRepresentationFlags" ; "ModuleSuffix" ]
|> SynExpr.createLongIdent
|> SynExpr.paren
|> create (SynLongIdent.createS "CompilationRepresentation")
let internal requireQualifiedAccess : SynAttribute =
create (SynLongIdent.createS "RequireQualifiedAccess") (SynExpr.CreateConst ())
let internal autoOpen : SynAttribute =
create (SynLongIdent.createS "AutoOpen") (SynExpr.CreateConst ())

View File

@@ -1,15 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<RequireQualifiedAccess>]
module internal SynAttributes =
let ofAttrs (attrs : SynAttribute list) : SynAttributes =
attrs
|> List.map (fun a ->
{
Attributes = [ a ]
Range = range0
}
)

View File

@@ -1,233 +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 withMutability (mut : bool) (binding : SynBinding) : SynBinding =
match binding with
| SynBinding (pat, kind, inl, _, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia) ->
SynBinding (pat, kind, inl, mut, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia)
let withRecursion (isRec : bool) (binding : SynBinding) : SynBinding =
match binding with
| SynBinding (pat, kind, inl, mut, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia) ->
let trivia =
{ trivia with
LeadingKeyword =
match trivia.LeadingKeyword with
| SynLeadingKeyword.Let _ ->
if isRec then
SynLeadingKeyword.LetRec (range0, range0)
else
trivia.LeadingKeyword
| SynLeadingKeyword.LetRec _ ->
if isRec then
trivia.LeadingKeyword
else
trivia.LeadingKeyword
| existing ->
failwith
$"WoofWare.Myriad doesn't yet let you adjust the recursion modifier on a binding with modifier %O{existing}"
}
SynBinding (pat, kind, inl, mut, attrs, xml, valData, headPat, returnInfo, expr, range, debugPoint, trivia)
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)

View File

@@ -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)

View File

@@ -1,10 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<AutoOpen>]
module internal SynConstExt =
type SynConst with
static member Create (s : string) : SynConst =
SynConst.String (s, SynStringKind.Regular, range0)

View File

@@ -1,365 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.SyntaxTrivia
open Fantomas.FCS.Text.Range
[<AutoOpen>]
module internal SynExprExtensions =
type SynExpr with
static member CreateConst (s : string) : SynExpr =
SynExpr.Const (SynConst.Create s, range0)
static member CreateConst () : SynExpr = SynExpr.Const (SynConst.Unit, range0)
static member CreateConst (b : bool) : SynExpr = SynExpr.Const (SynConst.Bool b, range0)
static member CreateConst (c : char) : SynExpr =
// apparent Myriad bug: `IndexOf '?'` gets formatted as `IndexOf ?` which is clearly wrong
SynExpr.App (
ExprAtomicFlag.NonAtomic,
false,
SynExpr.Ident (Ident.create "char"),
SynExpr.CreateConst (int c),
range0
)
|> fun e -> SynExpr.Paren (e, range0, Some range0, 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.App (ExprAtomicFlag.NonAtomic, false, f, x, range0)
/// {f} {x}
let inline applyTo (x : SynExpr) (f : SynExpr) : SynExpr = applyFunction f x
let inline private createAppInfix (f : SynExpr) (x : SynExpr) =
SynExpr.App (ExprAtomicFlag.NonAtomic, true, f, x, range0)
let inline createLongIdent'' (ident : SynLongIdent) : SynExpr =
SynExpr.LongIdent (false, ident, None, range0)
let inline createLongIdent' (ident : Ident list) : SynExpr =
createLongIdent'' (SynLongIdent.create ident)
let inline createLongIdent (ident : string list) : SynExpr =
createLongIdent' (ident |> List.map Ident.create)
/// {expr} |> {func}
let pipeThroughFunction (func : SynExpr) (expr : SynExpr) : SynExpr =
createAppInfix (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) =
createAppInfix (createLongIdent'' SynLongIdent.eq) a |> applyTo b
/// {a} && {b}
let booleanAnd (a : SynExpr) (b : SynExpr) =
createAppInfix (createLongIdent'' SynLongIdent.booleanAnd) a |> applyTo b
/// {a} || {b}
let booleanOr (a : SynExpr) (b : SynExpr) =
createAppInfix (createLongIdent'' SynLongIdent.booleanOr) a |> applyTo b
/// {a} + {b}
let plus (a : SynExpr) (b : SynExpr) =
createAppInfix (createLongIdent'' SynLongIdent.plus) a |> applyTo b
/// {a} * {b}
let times (a : SynExpr) (b : SynExpr) =
createAppInfix (createLongIdent'' SynLongIdent.times) a |> applyTo b
let rec stripOptionalParen (expr : SynExpr) : SynExpr =
match expr with
| SynExpr.Paren (expr, _, _, _) -> stripOptionalParen expr
| expr -> expr
let dotGet (field : string) (obj : SynExpr) : SynExpr =
SynExpr.DotGet (
obj,
range0,
SynLongIdent.SynLongIdent (id = [ Ident.create field ], dotRanges = [], trivia = [ None ]),
range0
)
/// {obj}.{meth} {arg}
let callMethodArg (meth : string) (arg : SynExpr) (obj : SynExpr) : SynExpr = dotGet meth obj |> applyTo arg
/// {obj}.{meth}()
let callMethod (meth : string) (obj : SynExpr) : SynExpr =
callMethodArg meth (SynExpr.CreateConst ()) obj
let typeApp (types : SynType list) (operand : SynExpr) =
SynExpr.TypeApp (operand, range0, types, List.replicate (types.Length - 1) range0, Some range0, range0, range0)
/// {obj}.{meth}<types,...>()
let callGenericMethod (meth : SynLongIdent) (types : SynType list) (obj : SynExpr) : SynExpr =
SynExpr.DotGet (obj, range0, meth, range0)
|> typeApp types
|> applyTo (SynExpr.CreateConst ())
/// {obj}.{meth}<ty>()
let callGenericMethod' (meth : string) (ty : string) (obj : SynExpr) : SynExpr =
callGenericMethod (SynLongIdent.createS meth) [ SynType.createLongIdent' [ ty ] ] obj
let inline index (property : SynExpr) (obj : SynExpr) : SynExpr =
SynExpr.DotIndexedGet (obj, property, range0, range0)
let inline arrayIndexRange (start : SynExpr option) (endRange : SynExpr option) (arr : SynExpr) : SynExpr =
SynExpr.DotIndexedGet (
arr,
(SynExpr.IndexRange (start, range0, endRange, range0, range0, range0)),
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 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 createForEach (pat : SynPat) (enumExpr : SynExpr) (body : SynExpr) : SynExpr =
SynExpr.ForEach (
DebugPointAtFor.No,
DebugPointAtInOrTo.No,
SeqExprOnly.SeqExprOnly false,
true,
pat,
enumExpr,
body,
range0
)
let inline createLet (bindings : SynBinding list) (body : SynExpr) : SynExpr =
SynExpr.LetOrUse (false, false, bindings, body, range0, SynExprLetOrUseTrivia.empty)
let inline createDo (body : SynExpr) : SynExpr = SynExpr.Do (body, range0)
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))
let listLiteral (elts : SynExpr list) : SynExpr =
SynExpr.ArrayOrListComputed (false, sequential elts, range0)
let arrayLiteral (elts : SynExpr list) : SynExpr =
SynExpr.ArrayOrListComputed (true, sequential elts, 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 =
createAppInfix (createLongIdent'' SynLongIdent.sub) (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 =
createAppInfix (createLongIdent'' SynLongIdent.gt) y |> applyTo x
/// {y} < {x}
let lessThan (x : SynExpr) (y : SynExpr) : SynExpr =
createAppInfix (createLongIdent'' SynLongIdent.lt) y |> applyTo x
/// {y} >= {x}
let greaterThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr =
createAppInfix (createLongIdent'' SynLongIdent.geq) y |> applyTo x
/// {y} <= {x}
let lessThanOrEqual (x : SynExpr) (y : SynExpr) : SynExpr =
createAppInfix (createLongIdent'' SynLongIdent.leq) y |> applyTo x
/// {x} :: {y}
let listCons (x : SynExpr) (y : SynExpr) : SynExpr =
createAppInfix
(SynExpr.LongIdent (
false,
SynLongIdent.SynLongIdent (
[ Ident.create "op_ColonColon" ],
[],
[ Some (IdentTrivia.OriginalNotation "::") ]
),
None,
range0
))
(tupleNoParen [ x ; y ])
|> paren
let assign (lhs : SynLongIdent) (rhs : SynExpr) : SynExpr = SynExpr.LongIdentSet (lhs, rhs, range0)
let assignIndex (lhs : SynExpr) (index : SynExpr) (rhs : SynExpr) : SynExpr =
SynExpr.DotIndexedSet (lhs, index, rhs, range0, range0, range0)

View File

@@ -1,10 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.SyntaxTrivia
[<RequireQualifiedAccess>]
module internal SynExprLetOrUseTrivia =
let empty : SynExprLetOrUseTrivia =
{
InKeyword = None
}

View File

@@ -1,76 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Text.Range
open Fantomas.FCS.Syntax
open Fantomas.FCS.SyntaxTrivia
open Fantomas.FCS.Xml
/// The data needed to reconstitute a single piece of data within a union field, or a single record field.
/// This is generic on whether the field is identified. For example, in `type Foo = Blah of int`, the `int`
/// field is not identified; whereas in `type Foo = Blah of baz : int`, it is identified.
type SynFieldData<'Ident> =
{
/// Attributes on this field. I think you can only get these if this is a *record* field.
Attrs : SynAttribute list
/// The identifier of this field (see docstring for SynFieldData).
Ident : 'Ident
/// The type of the data contained in this field. For example, `type Foo = { Blah : int }`
/// has this being `int`.
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)

View File

@@ -1,10 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
[<RequireQualifiedAccess>]
module internal SynIdent =
let inline createI (i : Ident) : SynIdent = SynIdent.SynIdent (i, None)
let inline createS (i : string) : SynIdent =
SynIdent.SynIdent (Ident.create i, None)

View File

@@ -1,140 +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 leq =
SynLongIdent.SynLongIdent (
[ Ident.create "op_LessThanOrEqual" ],
[],
[ Some (IdentTrivia.OriginalNotation "<=") ]
)
let gt =
SynLongIdent.SynLongIdent ([ Ident.create "op_GreaterThan" ], [], [ Some (IdentTrivia.OriginalNotation ">") ])
let lt =
SynLongIdent.SynLongIdent ([ Ident.create "op_LessThan" ], [], [ 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 booleanAnd =
SynLongIdent.SynLongIdent ([ Ident.create "op_BooleanAnd" ], [], [ Some (IdentTrivia.OriginalNotation "&&") ])
let booleanOr =
SynLongIdent.SynLongIdent ([ Ident.create "op_BooleanOr" ], [], [ Some (IdentTrivia.OriginalNotation "||") ])
let plus =
SynLongIdent.SynLongIdent ([ Ident.create "op_Addition" ], [], [ Some (IdentTrivia.OriginalNotation "+") ])
let times =
SynLongIdent.SynLongIdent ([ Ident.create "op_Multiply" ], [], [ 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 isChoice (ident : SynLongIdent) : bool =
match ident.LongIdent with
| [ i ] when System.String.Equals (i.idText, "Choice", System.StringComparison.Ordinal) -> true
// TODO: consider Microsoft.FSharp.Choice or whatever it is
| _ -> false
let isNullable (ident : SynLongIdent) : bool =
match ident.LongIdent |> List.map _.idText with
| [ "System" ; "Nullable" ]
| [ "Nullable" ] -> true
| _ -> 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

View File

@@ -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)

View File

@@ -1,71 +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
(attrs : SynAttribute list)
(ident : SynIdent)
(typars : SynTyparDecls option)
(arity : SynValInfo)
(xmlDoc : PreXmlDoc)
(returnType : SynType)
: SynMemberDefn
=
let slot =
SynValSig.SynValSig (
attrs
|> List.map (fun attr ->
{
Attributes = [ attr ]
Range = range0
}
),
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)

View File

@@ -1,30 +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 inline createTypes (tys : SynTypeDefn list) : SynModuleDecl = SynModuleDecl.Types (tys, range0)
let nestedModule (info : SynComponentInfo) (decls : SynModuleDecl list) : SynModuleDecl =
SynModuleDecl.NestedModule (
info,
false,
decls,
false,
range0,
{
ModuleKeyword = Some range0
EqualsRange = Some range0
}
)

View File

@@ -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
}
)

View File

@@ -1,54 +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 anon : SynPat = SynPat.Wild 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 nameWithArgs (i : string) (args : SynPat list) : SynPat =
identWithArgs [ Ident.create i ] (SynArgPats.create args)
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
let emptyList = SynPat.ArrayOrList (false, [], range0)
let listCons (lhs : SynPat) (rhs : SynPat) =
SynPat.ListCons (
lhs,
rhs,
range0,
{
ColonColonRange = range0
}
)
let emptyArray = SynPat.ArrayOrList (true, [], range0)

View File

@@ -1,10 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<RequireQualifiedAccess>]
module internal SynSimplePat =
let createId (id : Ident) : SynSimplePat =
SynSimplePat.Id (id, None, false, false, false, range0)

View File

@@ -1,12 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<RequireQualifiedAccess>]
module internal SynSimplePats =
let create (pats : SynSimplePat list) : SynSimplePats =
match pats with
| [] -> SynSimplePats.SimplePats ([], [], range0)
| pats -> SynSimplePats.SimplePats (pats, List.replicate (pats.Length - 1) range0, range0)

View File

@@ -1,539 +0,0 @@
namespace WoofWare.Myriad.Plugins
open System
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
[<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 (|ChoiceType|_|) (fieldType : SynType) =
match fieldType with
| SynType.App (SynType.LongIdent ident, _, inner, _, _, _, _) when SynLongIdent.isChoice ident -> Some inner
| _ -> None
let (|NullableType|_|) (fieldType : SynType) =
match fieldType with
| SynType.App (SynType.LongIdent ident, _, [ innerType ], _, _, _, _) when SynLongIdent.isNullable 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 ] ->
// We won't bother with the case that the user has done e.g. `Single` (relying on `System` being open).
match Primitives.qualifyType i.idText with
| Some qualified ->
match i.idText with
| "char"
| "string" -> None
| _ -> Some qualified
| None -> None
| _ -> None
| _ -> None
/// Returns the name of the measure, and the outer type.
let (|Measure|_|) (fieldType : SynType) : (Ident * LongIdent) option =
match fieldType with
| SynType.App (NumberType outer,
_,
[ SynType.LongIdent (SynLongIdent.SynLongIdent ([ ident ], _, _)) ],
_,
_,
_,
_) -> Some (ident, outer)
| _ -> None
let (|JsonNode|_|) (fieldType : SynType) : unit option =
match fieldType with
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
match ident |> List.map (fun i -> i.idText) with
| [ "System" ; "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
| [ "Text" ; "Json" ; "Nodes" ; "JsonNode" ]
| [ "Json" ; "Nodes" ; "JsonNode" ]
| [ "Nodes" ; "JsonNode" ]
| [ "JsonNode" ] -> Some ()
| _ -> None
| _ -> None
let (|Unit|_|) (fieldType : SynType) : unit option =
match fieldType with
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
match ident |> List.map (fun i -> i.idText.ToLowerInvariant ()) with
| [ "microsoft" ; "fsharp" ; "core" ; "unit" ]
| [ "fsharp" ; "core" ; "unit" ]
| [ "core" ; "unit" ]
| [ "unit" ] -> Some ()
| _ -> 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 (|DateTimeOffset|_|) (fieldType : SynType) =
match fieldType with
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
match ident |> List.map (fun i -> i.idText) with
| [ "System" ; "DateTimeOffset" ]
| [ "DateTimeOffset" ] -> 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
let (|DirectoryInfo|_|) (fieldType : SynType) =
match fieldType with
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
match ident |> List.map (fun i -> i.idText) with
| [ "System" ; "IO" ; "DirectoryInfo" ]
| [ "IO" ; "DirectoryInfo" ]
| [ "DirectoryInfo" ] -> Some ()
| _ -> None
| _ -> None
let (|FileInfo|_|) (fieldType : SynType) =
match fieldType with
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
match ident |> List.map (fun i -> i.idText) with
| [ "System" ; "IO" ; "FileInfo" ]
| [ "IO" ; "FileInfo" ]
| [ "FileInfo" ] -> Some ()
| _ -> None
| _ -> None
let (|TimeSpan|_|) (fieldType : SynType) =
match fieldType with
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) ->
match ident |> List.map (fun i -> i.idText) with
| [ "System" ; "TimeSpan" ]
| [ "TimeSpan" ] -> Some ()
| _ -> None
| _ -> None
[<RequireQualifiedAccess>]
module internal SynType =
let rec stripOptionalParen (ty : SynType) : SynType =
match ty with
| SynType.Paren (ty, _) -> stripOptionalParen ty
| ty -> ty
let inline paren (ty : SynType) : SynType = SynType.Paren (ty, range0)
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
/// Returns None if the input list was empty.
let inline tupleNoParen (ty : SynType list) : SynType option =
match List.rev ty with
| [] -> None
| [ t ] -> Some t
| t :: rest ->
([ SynTupleTypeSegment.Type t ], rest)
||> List.fold (fun ty nextArg -> SynTupleTypeSegment.Type nextArg :: SynTupleTypeSegment.Star range0 :: ty)
|> fun segs -> SynType.Tuple (false, segs, range0)
|> Some
let inline appPostfix (name : string) (arg : SynType) : SynType =
SynType.App (named name, None, [ arg ], [], None, true, range0)
let inline appPostfix' (name : string list) (arg : SynType) : SynType =
SynType.App (createLongIdent' name, None, [ arg ], [], None, true, range0)
let inline funFromDomain (domain : SynType) (range : SynType) : SynType =
SynType.Fun (
domain,
range,
range0,
{
ArrowRange = range0
}
)
let inline signatureParamOfType
(attrs : SynAttribute list)
(ty : SynType)
(optional : bool)
(name : Ident option)
: SynType
=
SynType.SignatureParameter (
attrs
|> List.map (fun attr ->
{
Attributes = [ attr ]
Range = range0
}
),
optional,
name,
ty,
range0
)
let inline var (ty : SynTypar) : SynType = SynType.Var (ty, range0)
let unit : SynType = named "unit"
let obj : SynType = named "obj"
let bool : SynType = named "bool"
let int : SynType = named "int"
let array (elt : SynType) : SynType = SynType.Array (1, elt, range0)
let list (elt : SynType) : SynType =
SynType.App (named "list", None, [ elt ], [], None, true, range0)
let option (elt : SynType) : SynType =
SynType.App (named "option", None, [ elt ], [], None, true, range0)
let anon : SynType = SynType.Anon range0
let task (elt : SynType) : SynType =
SynType.App (
createLongIdent' [ "System" ; "Threading" ; "Tasks" ; "Task" ],
None,
[ elt ],
[],
None,
true,
range0
)
let string : SynType = named "string"
/// 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)
let primitiveToHumanReadableString (name : LongIdent) : string =
match name |> List.map _.idText with
| [ "System" ; "Single" ] -> "single"
| [ "System" ; "Double" ] -> "double"
| [ "System" ; "Byte" ] -> "byte"
| [ "System" ; "SByte" ] -> "signed byte"
| [ "System" ; "Int16" ] -> "int16"
| [ "System" ; "Int32" ] -> "int32"
| [ "System" ; "Int64" ] -> "int64"
| [ "System" ; "UInt16" ] -> "uint16"
| [ "System" ; "UInt32" ] -> "uint32"
| [ "System" ; "UInt64" ] -> "uint64"
| [ "System" ; "Char" ] -> "char"
| [ "System" ; "Decimal" ] -> "decimal"
| [ "System" ; "String" ] -> "string"
| [ "System" ; "Boolean" ] -> "bool"
| ty ->
ty
|> String.concat "."
|> failwithf "could not create human-readable string for primitive type %s"
let rec toHumanReadableString (ty : SynType) : string =
match ty with
| PrimitiveType t1 -> primitiveToHumanReadableString t1
| OptionType t1 -> toHumanReadableString t1 + " option"
| NullableType t1 -> toHumanReadableString t1 + " Nullable"
| ChoiceType ts ->
ts
|> List.map toHumanReadableString
|> String.concat ", "
|> sprintf "Choice<%s>"
| MapType (k, v)
| DictionaryType (k, v)
| IDictionaryType (k, v)
| IReadOnlyDictionaryType (k, v) -> sprintf "map<%s, %s>" (toHumanReadableString k) (toHumanReadableString v)
| ListType t1 -> toHumanReadableString t1 + " list"
| ArrayType t1 -> toHumanReadableString t1 + " array"
| Task t1 -> toHumanReadableString t1 + " Task"
| UnitType -> "unit"
| FileInfo -> "FileInfo"
| DirectoryInfo -> "DirectoryInfo"
| Uri -> "URI"
| Stream -> "Stream"
| Guid -> "GUID"
| BigInt -> "bigint"
| DateTimeOffset -> "DateTimeOffset"
| DateOnly -> "DateOnly"
| TimeSpan -> "TimeSpan"
| SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> ident |> List.map _.idText |> String.concat "."
| ty -> failwithf "could not compute human-readable string for type: %O" ty
/// Guess whether the types are equal. We err on the side of saying "no, they're different".
let rec provablyEqual (ty1 : SynType) (ty2 : SynType) : bool =
if Object.ReferenceEquals (ty1, ty2) then
true
else
match ty1 with
| PrimitiveType t1 ->
match ty2 with
| PrimitiveType t2 -> (t1 |> List.map _.idText) = (t2 |> List.map _.idText)
| _ -> false
| OptionType t1 ->
match ty2 with
| OptionType t2 -> provablyEqual t1 t2
| _ -> false
| NullableType t1 ->
match ty2 with
| NullableType t2 -> provablyEqual t1 t2
| _ -> false
| ChoiceType t1 ->
match ty2 with
| ChoiceType t2 ->
t1.Length = t2.Length
&& List.forall (fun (a, b) -> provablyEqual a b) (List.zip t1 t2)
| _ -> false
| DictionaryType (k1, v1) ->
match ty2 with
| DictionaryType (k2, v2) -> provablyEqual k1 k2 && provablyEqual v1 v2
| _ -> false
| IDictionaryType (k1, v1) ->
match ty2 with
| IDictionaryType (k2, v2) -> provablyEqual k1 k2 && provablyEqual v1 v2
| _ -> false
| IReadOnlyDictionaryType (k1, v1) ->
match ty2 with
| IReadOnlyDictionaryType (k2, v2) -> provablyEqual k1 k2 && provablyEqual v1 v2
| _ -> false
| MapType (k1, v1) ->
match ty2 with
| MapType (k2, v2) -> provablyEqual k1 k2 && provablyEqual v1 v2
| _ -> false
| ListType t1 ->
match ty2 with
| ListType t2 -> provablyEqual t1 t2
| _ -> false
| ArrayType t1 ->
match ty2 with
| ArrayType t2 -> provablyEqual t1 t2
| _ -> false
| Task t1 ->
match ty2 with
| Task t2 -> provablyEqual t1 t2
| _ -> false
| UnitType ->
match ty2 with
| UnitType -> true
| _ -> false
| FileInfo ->
match ty2 with
| FileInfo -> true
| _ -> false
| DirectoryInfo ->
match ty2 with
| DirectoryInfo -> true
| _ -> false
| Uri ->
match ty2 with
| Uri -> true
| _ -> false
| Stream ->
match ty2 with
| Stream -> true
| _ -> false
| Guid ->
match ty2 with
| Guid -> true
| _ -> false
| BigInt ->
match ty2 with
| BigInt -> true
| _ -> false
| DateTimeOffset ->
match ty2 with
| DateTimeOffset -> true
| _ -> false
| DateOnly ->
match ty2 with
| DateOnly -> true
| _ -> false
| _ ->
match ty1, ty2 with
| SynType.LongIdent (SynLongIdent (ident1, _, _)), SynType.LongIdent (SynLongIdent (ident2, _, _)) ->
let ident1 = ident1 |> List.map _.idText
let ident2 = ident2 |> List.map _.idText
ident1 = ident2
| _, _ -> false

View File

@@ -1,46 +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)
let getName (defn : SynTypeDefn) : LongIdent =
match defn with
| SynTypeDefn (SynComponentInfo.SynComponentInfo (_, _, _, id, _, _, _, _), _, _, _, _, _) -> id
let getAttribute (attrName : string) (defn : SynTypeDefn) : SynAttribute option =
match defn with
| SynTypeDefn (SynComponentInfo.SynComponentInfo (attrs, _, _, _, _, _, _, _), _, _, _, _, _) ->
attrs
|> List.collect (fun a -> a.Attributes)
|> List.tryFind (fun i ->
match i.TypeName with
| SynLongIdent.SynLongIdent (id, _, _) ->
let name = List.last(id).idText
name = attrName || name + "Attribute" = attrName
)
let hasAttribute (attrName : string) (defn : SynTypeDefn) : bool =
getAttribute attrName defn |> Option.isSome

View File

@@ -1,24 +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 unionWithAccess (implAccess : SynAccess option) (cases : SynUnionCase list) : SynTypeDefnRepr =
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union (implAccess, cases, range0), range0)
let inline union (cases : SynUnionCase list) : SynTypeDefnRepr = unionWithAccess None cases
let inline recordWithAccess (implAccess : SynAccess option) (fields : SynField list) : SynTypeDefnRepr =
SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (implAccess, fields, range0), range0)
let inline record (fields : SynField list) : SynTypeDefnRepr = recordWithAccess None fields

View File

@@ -1,55 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
open Fantomas.FCS.Text.Range
open Fantomas.FCS.Xml
open Fantomas.FCS.SyntaxTrivia
/// Represents everything you need to know about a union case.
/// This is generic on whether each field of this case must be named.
type UnionCase<'ident> =
{
/// The name of the case: e.g. `| Foo of blah` has this being `Foo`.
Name : Ident
/// Any docstring associated with this case.
XmlDoc : PreXmlDoc option
/// Any accessibility modifier: e.g. `type Foo = private | Blah`.
Access : SynAccess option
/// Attributes on the case: for example, `| [<Attr>] Foo of blah`.
Attributes : SynAttribute list
/// The data contained within the case: for example, `[blah]` in `| Foo of blah`.
Fields : SynFieldData<'ident> list
}
[<RequireQualifiedAccess>]
module internal SynUnionCase =
let create (case : UnionCase<Ident option>) : SynUnionCase =
let fields =
case.Fields
|> List.map (fun field ->
SynField.SynField (
SynAttributes.ofAttrs field.Attrs,
false,
field.Ident,
field.Type,
false,
PreXmlDoc.Empty,
None,
range0,
{
LeadingKeyword = None
}
)
)
SynUnionCase.SynUnionCase (
SynAttributes.ofAttrs case.Attributes,
SynIdent.createI case.Name,
SynUnionCaseKind.Fields fields,
case.XmlDoc |> Option.defaultValue PreXmlDoc.Empty,
case.Access,
range0,
{
BarRange = Some range0
}
)

View File

@@ -1,7 +0,0 @@
namespace WoofWare.Myriad.Plugins
open Fantomas.FCS.Syntax
[<RequireQualifiedAccess>]
module internal SynValInfo =
let empty = SynValInfo.SynValInfo ([], SynArgInfo.empty)

View File

@@ -1,18 +0,0 @@
namespace WoofWare.Myriad.Plugins
// Extracted from https://github.com/G-Research/TypeEquality
// which is Apache-2.0 licenced. See `TeqLicence.txt`.
// We inline this code because Myriad doesn't seem to reliably load package references in the generator.
// I have reformatted a little, and stripped out all the code I don't use.
type internal Teq<'a, 'b> = private | Teq of ('a -> 'b) * ('b -> 'a)
[<RequireQualifiedAccess>]
module internal Teq =
let refl<'a> : Teq<'a, 'a> = Teq (id, id)
let cast (Teq (f, _)) a = f a
[<RequireQualifiedAccess>]
module Cong =
let believeMe<'a, 'b, 'a2, 'b2> (_ : Teq<'a, 'b>) : Teq<'a2, 'b2> = unbox <| (refl : Teq<'a2, 'a2>)

View File

@@ -15,10 +15,14 @@
<WarnOn>FS3559</WarnOn>
<PackageId>WoofWare.Myriad.Plugins</PackageId>
<PackageIcon>logo.png</PackageIcon>
<NoWarn>NU5118</NoWarn>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Myriad.Core" Version="0.8.3" />
<PackageReference Include="TypeEquality" Version="0.3.0" />
<PackageReference Include="WoofWare.Whippet.Fantomas" Version="0.5.1" />
<!-- the lowest version allowed by Myriad.Core -->
<PackageReference Update="FSharp.Core" Version="6.0.1" PrivateAssets="all"/>
</ItemGroup>
@@ -26,37 +30,9 @@
<ItemGroup>
<Compile Include="List.fs"/>
<Compile Include="Text.fs" />
<Compile Include="Teq.fs" />
<Compile Include="Primitives.fs" />
<Compile Include="SynExpr\SynAttributes.fs" />
<Compile Include="SynExpr\SynConst.fs" />
<Compile Include="SynExpr\SynArgInfo.fs" />
<Compile Include="SynExpr\SynValInfo.fs" />
<Compile Include="SynExpr\PreXmlDoc.fs" />
<Compile Include="SynExpr\Ident.fs" />
<Compile Include="SynExpr\SynSimplePat.fs" />
<Compile Include="SynExpr\SynSimplePats.fs" />
<Compile Include="SynExpr\SynIdent.fs" />
<Compile Include="SynExpr\SynLongIdent.fs" />
<Compile Include="SynExpr\SynExprLetOrUseTrivia.fs" />
<Compile Include="SynExpr\SynArgPats.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\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="Measure.fs" />
<Compile Include="AstHelper.fs" />
<Compile Include="Parameters.fs" />
<Compile Include="RemoveOptionsGenerator.fs"/>
<Compile Include="MyriadParamParser.fs" />
<Compile Include="InterfaceMockGenerator.fs"/>
@@ -67,7 +43,7 @@
<Compile Include="ArgParserGenerator.fs" />
<Compile Include="Swagger.fs" />
<Compile Include="SwaggerClientGenerator.fs" />
<None Include="TeqLicence.txt" />
<None Include="ApacheLicence.txt" />
<EmbeddedResource Include="version.json"/>
<EmbeddedResource Include="SurfaceBaseline.txt"/>
<None Include="..\README.md">
@@ -84,7 +60,7 @@
<ProjectReference Include="..\WoofWare.Myriad.Plugins.Attributes\WoofWare.Myriad.Plugins.Attributes.fsproj"/>
<!-- NuGet is such a clown package manager! Get the DLLs into the Nupkg artefact, I have no idea why this is needed,
but without this line, we don't get any dependency at all packaged into the resulting artefact. -->
<None Include="$(OutputPath)\WoofWare.Myriad.Plugins.Attributes.dll" Pack="true" PackagePath="lib\$(TargetFramework)"/>
<None Include="$(OutputPath)\*.dll" Pack="true" PackagePath="lib\$(TargetFramework)"/>
</ItemGroup>
</Project>

View File

@@ -1,5 +1,5 @@
{
"version": "3.1",
"version": "4.0",
"publicReleaseRefSpec": [
"^refs/heads/main$"
],

View File

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

12
flake.lock generated
View File

@@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1727524699,
"narHash": "sha256-k6YxGj08voz9NvuKExojiGXAVd69M8COtqWSKr6sQS4=",
"lastModified": 1744502386,
"narHash": "sha256-QAd1L37eU7ktL2WeLLLTmI6P9moz9+a/ONO8qNBYJgM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b5b2fecd0cadd82ef107c9583018f381ae70f222",
"rev": "f6db44a8daa59c40ae41ba6e5823ec77fe0d2124",
"type": "github"
},
"original": {

View File

@@ -14,8 +14,8 @@
flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
pname = "WoofWare.Myriad.Plugins";
dotnet-sdk = pkgs.dotnet-sdk_8;
dotnet-runtime = pkgs.dotnetCorePackages.runtime_8_0;
dotnet-sdk = pkgs.dotnetCorePackages.sdk_9_0;
dotnet-runtime = pkgs.dotnetCorePackages.runtime_9_0;
version = "0.1";
dotnetTool = dllOverride: toolName: toolVersion: hash:
pkgs.stdenvNoCC.mkDerivation rec {
@@ -26,25 +26,29 @@
pname = name;
version = version;
hash = hash;
installPhase = ''mkdir -p $out/bin && cp -r tools/net6.0/any/* $out/bin'';
installPhase = ''mkdir -p $out/bin && cp -r tools/net*/any/* $out/bin'';
};
installPhase = let
dll =
if isNull dllOverride
then name
else dllOverride;
in ''
runHook preInstall
mkdir -p "$out/lib"
cp -r ./bin/* "$out/lib"
makeWrapper "${dotnet-runtime}/bin/dotnet" "$out/bin/${name}" --add-flags "$out/lib/${dll}.dll"
runHook postInstall
'';
in
# fsharp-analyzers requires the .NET SDK at runtime, so we use that instead of dotnet-runtime.
''
runHook preInstall
mkdir -p "$out/lib"
cp -r ./bin/* "$out/lib"
makeWrapper "${dotnet-sdk}/bin/dotnet" "$out/bin/${name}" --set DOTNET_HOST_PATH "${dotnet-sdk}/bin/dotnet" --add-flags "$out/lib/${dll}.dll"
runHook postInstall
'';
};
in {
packages = {
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).hash;
fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).hash;
packages = let
deps = builtins.fromJSON (builtins.readFile ./nix/deps.json);
in {
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") deps)).hash;
fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") deps)).hash;
default = pkgs.buildDotnetModule {
inherit pname version dotnet-sdk dotnet-runtime;
name = "WoofWare.Myriad.Plugins";
@@ -52,7 +56,7 @@
projectFile = "./WoofWare.Myriad.Plugins/WoofWare.Myriad.Plugins.fsproj";
testProjectFile = "./WoofWare.Myriad.Plugins.Test/WoofWare.Myriad.Plugins.Test.fsproj";
disabledTests = ["WoofWare.Myriad.Plugins.Test.TestSurface.CheckVersionAgainstRemote"];
nugetDeps = ./nix/deps.nix; # `nix build .#default.passthru.fetch-deps && ./result nix/deps.nix`
nugetDeps = ./nix/deps.json; # `nix build .#default.fetch-deps && ./result nix/deps.json`
doCheck = true;
};
};

View File

@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.100",
"rollForward": "latestMajor"
}
}
{
"sdk": {
"version": "9.0.100",
"rollForward": "latestMajor"
}
}

387
nix/deps.json Normal file
View File

@@ -0,0 +1,387 @@
[
{
"pname": "ApiSurface",
"version": "4.1.20",
"hash": "sha256-koWgO9FC9ax+Ij56ug8kxeyknl0yhLqnNLOUdxtqqo4="
},
{
"pname": "fantomas",
"version": "7.0.1",
"hash": "sha256-2aGD6Kjh83gmssRqqZ/Uihi7VbNqNUelX4otIfCuhTI="
},
{
"pname": "Fantomas.Core",
"version": "6.1.1",
"hash": "sha256-FcTLHQFvKkQY/kV08jhhy/St/+FmXpp3epp/R3zUXMA="
},
{
"pname": "Fantomas.FCS",
"version": "6.1.1",
"hash": "sha256-NuZ8msPEHYA8T3EYREB28F1RcNgUU8V54eg2+UttYxw="
},
{
"pname": "FsCheck",
"version": "3.2.0",
"hash": "sha256-ksZ4vLgWwyQOzFuK2BczdtDtWWYmedG7UBAg4pYuI8g="
},
{
"pname": "fsharp-analyzers",
"version": "0.30.0",
"hash": "sha256-7oaSwpHAU1opzpz4szLU/gDaJC/ww9eiFkPu0nr4Mj4="
},
{
"pname": "FSharp.Core",
"version": "4.3.4",
"hash": "sha256-styyo+6mJy+yxE0NZG/b1hxkAjPOnJfMgd9zWzCJ5uk="
},
{
"pname": "FSharp.Core",
"version": "6.0.1",
"hash": "sha256-Ehsgt3nCJijpaVuJguC1TPVEKSkJd6PSc07D2ZQSemI="
},
{
"pname": "FSharp.Core",
"version": "9.0.202",
"hash": "sha256-64Gub0qemmCoMa1tDus6TeTuB1+5sHfE6KD2j4o84mA="
},
{
"pname": "FsUnit",
"version": "7.0.1",
"hash": "sha256-K85CIdxMeFSHEKZk6heIXp/oFjWAn7dBILKrw49pJUY="
},
{
"pname": "Microsoft.ApplicationInsights",
"version": "2.22.0",
"hash": "sha256-mUQ63atpT00r49ca50uZu2YCiLg3yd6r3HzTryqcuEA="
},
{
"pname": "Microsoft.AspNetCore.App.Ref",
"version": "6.0.36",
"hash": "sha256-9jDkWbjw/nd8yqdzVTagCuqr6owJ/DUMi4BlUZT4hWU="
},
{
"pname": "Microsoft.AspNetCore.App.Runtime.linux-arm64",
"version": "6.0.36",
"hash": "sha256-JQULJyF0ivLoUU1JaFfK/HHg+/qzpN7V2RR2Cc+WlQ4="
},
{
"pname": "Microsoft.AspNetCore.App.Runtime.linux-x64",
"version": "6.0.36",
"hash": "sha256-zUsVIpV481vMLAXaLEEUpEMA9/f1HGOnvaQnaWdzlyY="
},
{
"pname": "Microsoft.AspNetCore.App.Runtime.osx-arm64",
"version": "6.0.36",
"hash": "sha256-2seqZcz0JeUjkzh3QcGa9TcJ4LUafpFjTRk+Nm8T6T0="
},
{
"pname": "Microsoft.AspNetCore.App.Runtime.osx-x64",
"version": "6.0.36",
"hash": "sha256-yxLafxiBKkvfkDggPk0P9YZIHBkDJOsFTO7/V9mEHuU="
},
{
"pname": "Microsoft.CodeCoverage",
"version": "17.13.0",
"hash": "sha256-GKrIxeyQo5Az1mztfQgea1kGtJwonnNOrXK/0ULfu8o="
},
{
"pname": "Microsoft.NET.Test.Sdk",
"version": "17.13.0",
"hash": "sha256-sc2wvyV8cGm1FrNP2GGHEI584RCvRPu15erYCsgw5QY="
},
{
"pname": "Microsoft.NETCore.App.Host.linux-arm64",
"version": "6.0.36",
"hash": "sha256-9lC/LYnthYhjkWWz2kkFCvlA5LJOv11jdt59SDnpdy0="
},
{
"pname": "Microsoft.NETCore.App.Host.linux-x64",
"version": "6.0.36",
"hash": "sha256-VFRDzx7LJuvI5yzKdGmw/31NYVbwHWPKQvueQt5xc10="
},
{
"pname": "Microsoft.NETCore.App.Host.osx-arm64",
"version": "6.0.36",
"hash": "sha256-DaSWwYACJGolEBuMhzDVCj/rQTdDt061xCVi+gyQnuo="
},
{
"pname": "Microsoft.NETCore.App.Host.osx-x64",
"version": "6.0.36",
"hash": "sha256-FrRny9EI6HKCKQbu6mcLj5w4ooSRrODD4Vj2ZMGnMd4="
},
{
"pname": "Microsoft.NETCore.App.Ref",
"version": "6.0.36",
"hash": "sha256-9LZgVoIFF8qNyUu8kdJrYGLutMF/cL2K82HN2ywwlx8="
},
{
"pname": "Microsoft.NETCore.App.Runtime.linux-arm64",
"version": "6.0.36",
"hash": "sha256-k3rxvUhCEU0pVH8KgEMtkPiSOibn+nBh+0zT2xIfId8="
},
{
"pname": "Microsoft.NETCore.App.Runtime.linux-x64",
"version": "6.0.36",
"hash": "sha256-U8wJ2snSDFqeAgDVLXjnniidC7Cr5aJ1/h/BMSlyu0c="
},
{
"pname": "Microsoft.NETCore.App.Runtime.osx-arm64",
"version": "6.0.36",
"hash": "sha256-UfLcrL2Gj/OLz0s92Oo+OCJeDpZFAcQLPLiSNND8D5Y="
},
{
"pname": "Microsoft.NETCore.App.Runtime.osx-x64",
"version": "6.0.36",
"hash": "sha256-0xIJYFzxdMcnCj3wzkFRQZSnQcPHzPHMzePRIOA3oJs="
},
{
"pname": "Microsoft.NETCore.Platforms",
"version": "1.1.0",
"hash": "sha256-FeM40ktcObQJk4nMYShB61H/E8B7tIKfl9ObJ0IOcCM="
},
{
"pname": "Microsoft.NETCore.Platforms",
"version": "1.1.1",
"hash": "sha256-8hLiUKvy/YirCWlFwzdejD2Db3DaXhHxT7GSZx/znJg="
},
{
"pname": "Microsoft.NETCore.Platforms",
"version": "2.0.0",
"hash": "sha256-IEvBk6wUXSdyCnkj6tHahOJv290tVVT8tyemYcR0Yro="
},
{
"pname": "Microsoft.NETCore.Targets",
"version": "1.1.0",
"hash": "sha256-0AqQ2gMS8iNlYkrD+BxtIg7cXMnr9xZHtKAuN4bjfaQ="
},
{
"pname": "Microsoft.NETCore.Targets",
"version": "1.1.3",
"hash": "sha256-WLsf1NuUfRWyr7C7Rl9jiua9jximnVvzy6nk2D2bVRc="
},
{
"pname": "Microsoft.Testing.Extensions.Telemetry",
"version": "1.5.3",
"hash": "sha256-bIXwPSa3jkr2b6xINOqMUs6/uj/r4oVFM7xq3uVIZDU="
},
{
"pname": "Microsoft.Testing.Extensions.TrxReport.Abstractions",
"version": "1.5.3",
"hash": "sha256-IfMRfcyaIKEMRtx326ICKtinDBEfGw/Sv8ZHawJ96Yc="
},
{
"pname": "Microsoft.Testing.Extensions.VSTestBridge",
"version": "1.5.3",
"hash": "sha256-XpM/yFjhLSsuzyDV+xKubs4V1zVVYiV05E0+N4S1h0g="
},
{
"pname": "Microsoft.Testing.Platform",
"version": "1.5.3",
"hash": "sha256-y61Iih6w5D79dmrj2V675mcaeIiHoj1HSa1FRit2BLM="
},
{
"pname": "Microsoft.Testing.Platform.MSBuild",
"version": "1.5.3",
"hash": "sha256-YspvjE5Jfi587TAfsvfDVJXNrFOkx1B3y1CKV6m7YLY="
},
{
"pname": "Microsoft.TestPlatform.ObjectModel",
"version": "17.12.0",
"hash": "sha256-3XBHBSuCxggAIlHXmKNQNlPqMqwFlM952Av6RrLw1/w="
},
{
"pname": "Microsoft.TestPlatform.ObjectModel",
"version": "17.13.0",
"hash": "sha256-6S0fjfj8vA+h6dJVNwLi6oZhYDO/I/6hBZaq2VTW+Uk="
},
{
"pname": "Microsoft.TestPlatform.TestHost",
"version": "17.13.0",
"hash": "sha256-L/CJzou7dhmShUgXq3aXL3CaLTJll17Q+JY2DBdUUpo="
},
{
"pname": "Myriad.Core",
"version": "0.8.3",
"hash": "sha256-vBOxfq8QriX/yUtaXN69rEQaY/psRNJWxqATLidrt2g="
},
{
"pname": "Myriad.Sdk",
"version": "0.8.3",
"hash": "sha256-7O397WKhskKOvE3MkJT37BvxorDWngDR6gTUogtDZ2M="
},
{
"pname": "Nerdbank.GitVersioning",
"version": "3.8.38-alpha",
"hash": "sha256-gPMrVbjOZxXoofczF/pn6eVkLhjVSJIyQrLO2oljrDc="
},
{
"pname": "NETStandard.Library",
"version": "2.0.3",
"hash": "sha256-Prh2RPebz/s8AzHb2sPHg3Jl8s31inv9k+Qxd293ybo="
},
{
"pname": "Newtonsoft.Json",
"version": "13.0.1",
"hash": "sha256-K2tSVW4n4beRPzPu3rlVaBEMdGvWSv/3Q1fxaDh4Mjo="
},
{
"pname": "Newtonsoft.Json",
"version": "13.0.3",
"hash": "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc="
},
{
"pname": "NuGet.Common",
"version": "6.13.2",
"hash": "sha256-ASLa/Jigg5Eop0ZrXPl98RW2rxnJRC7pbbxhuV74hFw="
},
{
"pname": "NuGet.Configuration",
"version": "6.13.2",
"hash": "sha256-z8VW1YdRDanyyRTDYRvRkSv/XPR3c/hMM1y8cNNjx0Y="
},
{
"pname": "NuGet.Frameworks",
"version": "6.13.2",
"hash": "sha256-caDyc+WgYOo43AUTjtbP0MyvYDb6JweEKDdIul61Cac="
},
{
"pname": "NuGet.Packaging",
"version": "6.13.2",
"hash": "sha256-lhO+SFwIYZ4aPHxIGm5ubkkE2a5Ve2xgtroRbNh7hpw="
},
{
"pname": "NuGet.Protocol",
"version": "6.13.2",
"hash": "sha256-5lnAHHZjy7A4vgv65AeBAs64mSNpuoUjxW3HnrMpuzY="
},
{
"pname": "NuGet.Versioning",
"version": "6.13.2",
"hash": "sha256-gmpyBpKnt+GHqgx/2uFKp+J2csbxEAy1E7WdVT117sw="
},
{
"pname": "NUnit",
"version": "4.3.2",
"hash": "sha256-0RWe8uFoxYp6qhPlDDEghOMcKJgyw2ybvEoAqBLebeE="
},
{
"pname": "NUnit3TestAdapter",
"version": "5.0.0",
"hash": "sha256-7jZM4qAbIzne3AcdFfMbvbgogqpxvVe6q2S7Ls8xQy0="
},
{
"pname": "RestEase",
"version": "1.6.4",
"hash": "sha256-FFmqFwlHhIln46k56Z8KM1G+xuPEh/bceKCQnJcdcdc="
},
{
"pname": "runtime.any.System.Runtime",
"version": "4.3.0",
"hash": "sha256-qwhNXBaJ1DtDkuRacgHwnZmOZ1u9q7N8j0cWOLYOELM="
},
{
"pname": "runtime.native.System",
"version": "4.3.0",
"hash": "sha256-ZBZaodnjvLXATWpXXakFgcy6P+gjhshFXmglrL5xD5Y="
},
{
"pname": "runtime.unix.System.Private.Uri",
"version": "4.3.0",
"hash": "sha256-c5tXWhE/fYbJVl9rXs0uHh3pTsg44YD1dJvyOA0WoMs="
},
{
"pname": "System.Collections.Immutable",
"version": "8.0.0",
"hash": "sha256-F7OVjKNwpqbUh8lTidbqJWYi476nsq9n+6k0+QVRo3w="
},
{
"pname": "System.Diagnostics.DiagnosticSource",
"version": "5.0.0",
"hash": "sha256-6mW3N6FvcdNH/pB58pl+pFSCGWgyaP4hfVtC/SMWDV4="
},
{
"pname": "System.Diagnostics.DiagnosticSource",
"version": "7.0.0",
"hash": "sha256-9Wk8cHSkjKtqkN6xW7KnXoQVtF/VNbKeBq79WqDesMs="
},
{
"pname": "System.Formats.Asn1",
"version": "6.0.0",
"hash": "sha256-KaMHgIRBF7Nf3VwOo+gJS1DcD+41cJDPWFh+TDQ8ee8="
},
{
"pname": "System.Formats.Asn1",
"version": "8.0.1",
"hash": "sha256-may/Wg+esmm1N14kQTG4ESMBi+GQKPp0ZrrBo/o6OXM="
},
{
"pname": "System.IO.Abstractions",
"version": "4.2.13",
"hash": "sha256-nkC/PiqE6+c1HJ2yTwg3x+qdBh844Z8n3ERWDW8k6Gg="
},
{
"pname": "System.IO.FileSystem.AccessControl",
"version": "4.5.0",
"hash": "sha256-ck44YBQ0M+2Im5dw0VjBgFD1s0XuY54cujrodjjSBL8="
},
{
"pname": "System.Memory",
"version": "4.5.5",
"hash": "sha256-EPQ9o1Kin7KzGI5O3U3PUQAZTItSbk9h/i4rViN3WiI="
},
{
"pname": "System.Private.Uri",
"version": "4.3.0",
"hash": "sha256-fVfgcoP4AVN1E5wHZbKBIOPYZ/xBeSIdsNF+bdukIRM="
},
{
"pname": "System.Reflection.Metadata",
"version": "1.6.0",
"hash": "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E="
},
{
"pname": "System.Runtime",
"version": "4.3.1",
"hash": "sha256-R9T68AzS1PJJ7v6ARz9vo88pKL1dWqLOANg4pkQjkA0="
},
{
"pname": "System.Runtime.CompilerServices.Unsafe",
"version": "6.0.0",
"hash": "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I="
},
{
"pname": "System.Security.AccessControl",
"version": "4.5.0",
"hash": "sha256-AFsKPb/nTk2/mqH/PYpaoI8PLsiKKimaXf+7Mb5VfPM="
},
{
"pname": "System.Security.Cryptography.Pkcs",
"version": "6.0.4",
"hash": "sha256-2e0aRybote+OR66bHaNiYpF//4fCiaO3zbR2e9GABUI="
},
{
"pname": "System.Security.Cryptography.ProtectedData",
"version": "4.4.0",
"hash": "sha256-Ri53QmFX8I8UH0x4PikQ1ZA07ZSnBUXStd5rBfGWFOE="
},
{
"pname": "System.Security.Principal.Windows",
"version": "4.5.0",
"hash": "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY="
},
{
"pname": "System.Text.Json",
"version": "8.0.5",
"hash": "sha256-yKxo54w5odWT6nPruUVsaX53oPRe+gKzGvLnnxtwP68="
},
{
"pname": "TypeEquality",
"version": "0.3.0",
"hash": "sha256-V50xAOzzyUJrY+MYPRxtnqW5MVeATXCes89wPprv1r4="
},
{
"pname": "WoofWare.Whippet.Fantomas",
"version": "0.5.1",
"hash": "sha256-59CwnOZQAq5ZJoUkd87OiP8KUwx8xYDLMimMMTlKeZA="
}
]

View File

@@ -1,329 +0,0 @@
# This file was automatically generated by passthru.fetch-deps.
# Please dont edit it manually, your changes might get overwritten!
{fetchNuGet}: [
(fetchNuGet {
pname = "ApiSurface";
version = "4.1.5";
hash = "sha256-Kbt18XLk1gvZfzGca885HaXZB119APay85KzI546PYM=";
})
(fetchNuGet {
pname = "fantomas";
version = "6.3.15";
hash = "sha256-Gjw7MxjUNckMWSfnOye4UTe5fZWnor6RHCls3PNsuG8=";
})
(fetchNuGet {
pname = "Fantomas.Core";
version = "6.1.1";
hash = "sha256-FcTLHQFvKkQY/kV08jhhy/St/+FmXpp3epp/R3zUXMA=";
})
(fetchNuGet {
pname = "Fantomas.FCS";
version = "6.1.1";
hash = "sha256-NuZ8msPEHYA8T3EYREB28F1RcNgUU8V54eg2+UttYxw=";
})
(fetchNuGet {
pname = "FsCheck";
version = "2.16.6";
hash = "sha256-1hR2SaJTkqBzU3D955MvLNVzkQHkx0Z/QzOXZfzk2Zw=";
})
(fetchNuGet {
pname = "fsharp-analyzers";
version = "0.27.0";
hash = "sha256-QhLi2veTY1wZlQKJLTyVPgx/ImkaZugQNjSN5VJCNEA=";
})
(fetchNuGet {
pname = "FSharp.Core";
version = "4.3.4";
hash = "sha256-styyo+6mJy+yxE0NZG/b1hxkAjPOnJfMgd9zWzCJ5uk=";
})
(fetchNuGet {
pname = "FSharp.Core";
version = "6.0.1";
hash = "sha256-Ehsgt3nCJijpaVuJguC1TPVEKSkJd6PSc07D2ZQSemI=";
})
(fetchNuGet {
pname = "FSharp.Core";
version = "8.0.400";
hash = "sha256-wlrcAjjvI5YtnHR7kFH8uRUA4GomJYmqr41K5LYjCGs=";
})
(fetchNuGet {
pname = "FsUnit";
version = "6.0.1";
hash = "sha256-vka/aAgWhDCl5tu+kgO7GtSaHOOvlSaWxG+tExwGXpI=";
})
(fetchNuGet {
pname = "Microsoft.AspNetCore.App.Ref";
version = "6.0.33";
hash = "sha256-GcPiO+iI0JsHYlqURAmzWjOnDX2jDCUY4jYaIwr8ojs=";
})
(fetchNuGet {
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
version = "6.0.33";
hash = "sha256-g5zbB1DnCSKuCOWtF09GEqGn1uJLdlTN6kqdnSCzRjQ=";
})
(fetchNuGet {
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
version = "6.0.33";
hash = "sha256-ToaiqVy5qonomAVBg5PO1GgrPKL4Cc1BZTJ0z/2LquA=";
})
(fetchNuGet {
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
version = "6.0.33";
hash = "sha256-OY/vdqAzZ99I4lEZbOOQw12TE0AIb5pXxKTvDxO2M2Q=";
})
(fetchNuGet {
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
version = "6.0.33";
hash = "sha256-53MAV3RO1kXzy5IpdZDZIOhoUzFqWHn7+A3aWwdTONQ=";
})
(fetchNuGet {
pname = "Microsoft.CodeCoverage";
version = "17.11.1";
hash = "sha256-1dLlK3NGh88PuFYZiYpT+izA96etxhU3BSgixDgdtGA=";
})
(fetchNuGet {
pname = "Microsoft.NET.Test.Sdk";
version = "17.11.1";
hash = "sha256-0JUEucQ2lzaPgkrjm/NFLBTbqU1dfhvhN3Tl3moE6mI=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Host.linux-arm64";
version = "6.0.33";
hash = "sha256-rwWOpf2Pdg84c8bKIUcMYuDTI0kXUELL/nl9psSmX+E=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Host.linux-x64";
version = "6.0.33";
hash = "sha256-5iYNZATXOePDsLA9lI80o1Gjxw4E+B4bJbwdYJJHcZY=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Host.osx-arm64";
version = "6.0.33";
hash = "sha256-k3LenomOlacyzq4FlBY/TwV7+ClbK4U0A/O9r0pZHT4=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Host.osx-x64";
version = "6.0.33";
hash = "sha256-tu72AwDH1+oAIXjOJcNbeyKm1s4pncYp0avbMSBrcJQ=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Ref";
version = "6.0.33";
hash = "sha256-BiGUcXo1FQTlZdR6ndhUQ8lrYG3KaGXNXRVF+Fc3L28=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
version = "6.0.33";
hash = "sha256-obRKiJEVpZ5E3TE7q2oHaYwFYhI23rMiHwp+8ORkwXY=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
version = "6.0.33";
hash = "sha256-2xdhvnKsFc8utDWN09zeXzZ5op+WUqkoWLuzdtQAkrA=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
version = "6.0.33";
hash = "sha256-9KHubWicibZOcixiByzuBKPnJM2u5DSQC9jR3MAR1bI=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
version = "6.0.33";
hash = "sha256-smh6SiTtCAuFglqWrXiGGsoIDP9dhGuIKdYjmw+xCyY=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.Platforms";
version = "1.1.0";
hash = "sha256-FeM40ktcObQJk4nMYShB61H/E8B7tIKfl9ObJ0IOcCM=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.Platforms";
version = "1.1.1";
hash = "sha256-8hLiUKvy/YirCWlFwzdejD2Db3DaXhHxT7GSZx/znJg=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.Platforms";
version = "2.0.0";
hash = "sha256-IEvBk6wUXSdyCnkj6tHahOJv290tVVT8tyemYcR0Yro=";
})
(fetchNuGet {
pname = "Microsoft.NETCore.Targets";
version = "1.1.3";
hash = "sha256-WLsf1NuUfRWyr7C7Rl9jiua9jximnVvzy6nk2D2bVRc=";
})
(fetchNuGet {
pname = "Microsoft.TestPlatform.ObjectModel";
version = "17.11.1";
hash = "sha256-5vX+vCzFY3S7xfMVIv8OlMMFtdedW9UIJzc0WEc+vm4=";
})
(fetchNuGet {
pname = "Microsoft.TestPlatform.TestHost";
version = "17.11.1";
hash = "sha256-wSkY0H1fQAq0H3LcKT4u7Y5RzhAAPa6yueVN84g8HxU=";
})
(fetchNuGet {
pname = "Myriad.Core";
version = "0.8.3";
hash = "sha256-vBOxfq8QriX/yUtaXN69rEQaY/psRNJWxqATLidrt2g=";
})
(fetchNuGet {
pname = "Myriad.Sdk";
version = "0.8.3";
hash = "sha256-7O397WKhskKOvE3MkJT37BvxorDWngDR6gTUogtDZ2M=";
})
(fetchNuGet {
pname = "Nerdbank.GitVersioning";
version = "3.6.143";
hash = "sha256-OhOtMzP+2obDIR+npR7SsoXo0KrmcsL+VCE8Z3t5gzQ=";
})
(fetchNuGet {
pname = "NETStandard.Library";
version = "2.0.3";
hash = "sha256-Prh2RPebz/s8AzHb2sPHg3Jl8s31inv9k+Qxd293ybo=";
})
(fetchNuGet {
pname = "Newtonsoft.Json";
version = "13.0.1";
hash = "sha256-K2tSVW4n4beRPzPu3rlVaBEMdGvWSv/3Q1fxaDh4Mjo=";
})
(fetchNuGet {
pname = "Newtonsoft.Json";
version = "13.0.3";
hash = "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc=";
})
(fetchNuGet {
pname = "NuGet.Common";
version = "6.11.0";
hash = "sha256-eb7G07RyZv4AQT6ItRqdBuUf9e9BXcQygsy5RNEXfNE=";
})
(fetchNuGet {
pname = "NuGet.Configuration";
version = "6.11.0";
hash = "sha256-2SNZkX64SB15glzQx3k+vI7btr8Yqg4CayaaaK1B0AQ=";
})
(fetchNuGet {
pname = "NuGet.Frameworks";
version = "6.11.0";
hash = "sha256-8DC7V2IlCjiMDQ9yWbl7QQHia6OpBrbWh5rL0qa0Opw=";
})
(fetchNuGet {
pname = "NuGet.Packaging";
version = "6.11.0";
hash = "sha256-LVLvxcB6SMdayxAsrc5bCuLLt25fqPr6KfYcYoWWIQk=";
})
(fetchNuGet {
pname = "NuGet.Protocol";
version = "6.11.0";
hash = "sha256-3vdB/8IiJ2LMHhFXLWOzf0H59Ow/zcoq6W4uCHbihCQ=";
})
(fetchNuGet {
pname = "NuGet.Versioning";
version = "6.11.0";
hash = "sha256-03edgWvbqUtbzpBBTIxTwsSRoj1T2muGVL+vTuIHXag=";
})
(fetchNuGet {
pname = "NUnit";
version = "4.2.2";
hash = "sha256-+0OS67ITalmG9arYCgQF/+YbmPRnB3pIIykew0kvoCc=";
})
(fetchNuGet {
pname = "NUnit3TestAdapter";
version = "4.6.0";
hash = "sha256-9Yav2fYhC4w0OgsyUwU4/5rDy4FVDTpKnWHuwl/uKJQ=";
})
(fetchNuGet {
pname = "RestEase";
version = "1.6.4";
hash = "sha256-FFmqFwlHhIln46k56Z8KM1G+xuPEh/bceKCQnJcdcdc=";
})
(fetchNuGet {
pname = "runtime.any.System.Runtime";
version = "4.3.0";
hash = "sha256-qwhNXBaJ1DtDkuRacgHwnZmOZ1u9q7N8j0cWOLYOELM=";
})
(fetchNuGet {
pname = "runtime.native.System";
version = "4.3.0";
hash = "sha256-ZBZaodnjvLXATWpXXakFgcy6P+gjhshFXmglrL5xD5Y=";
})
(fetchNuGet {
pname = "runtime.unix.System.Private.Uri";
version = "4.3.0";
hash = "sha256-c5tXWhE/fYbJVl9rXs0uHh3pTsg44YD1dJvyOA0WoMs=";
})
(fetchNuGet {
pname = "System.Diagnostics.DiagnosticSource";
version = "7.0.0";
hash = "sha256-9Wk8cHSkjKtqkN6xW7KnXoQVtF/VNbKeBq79WqDesMs=";
})
(fetchNuGet {
pname = "System.Formats.Asn1";
version = "6.0.0";
hash = "sha256-KaMHgIRBF7Nf3VwOo+gJS1DcD+41cJDPWFh+TDQ8ee8=";
})
(fetchNuGet {
pname = "System.IO.Abstractions";
version = "4.2.13";
hash = "sha256-nkC/PiqE6+c1HJ2yTwg3x+qdBh844Z8n3ERWDW8k6Gg=";
})
(fetchNuGet {
pname = "System.IO.FileSystem.AccessControl";
version = "4.5.0";
hash = "sha256-ck44YBQ0M+2Im5dw0VjBgFD1s0XuY54cujrodjjSBL8=";
})
(fetchNuGet {
pname = "System.Memory";
version = "4.5.5";
hash = "sha256-EPQ9o1Kin7KzGI5O3U3PUQAZTItSbk9h/i4rViN3WiI=";
})
(fetchNuGet {
pname = "System.Private.Uri";
version = "4.3.0";
hash = "sha256-fVfgcoP4AVN1E5wHZbKBIOPYZ/xBeSIdsNF+bdukIRM=";
})
(fetchNuGet {
pname = "System.Reflection.Metadata";
version = "1.6.0";
hash = "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E=";
})
(fetchNuGet {
pname = "System.Runtime";
version = "4.3.1";
hash = "sha256-R9T68AzS1PJJ7v6ARz9vo88pKL1dWqLOANg4pkQjkA0=";
})
(fetchNuGet {
pname = "System.Runtime.CompilerServices.Unsafe";
version = "6.0.0";
hash = "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I=";
})
(fetchNuGet {
pname = "System.Security.AccessControl";
version = "4.5.0";
hash = "sha256-AFsKPb/nTk2/mqH/PYpaoI8PLsiKKimaXf+7Mb5VfPM=";
})
(fetchNuGet {
pname = "System.Security.Cryptography.Pkcs";
version = "6.0.4";
hash = "sha256-2e0aRybote+OR66bHaNiYpF//4fCiaO3zbR2e9GABUI=";
})
(fetchNuGet {
pname = "System.Security.Cryptography.ProtectedData";
version = "4.4.0";
hash = "sha256-Ri53QmFX8I8UH0x4PikQ1ZA07ZSnBUXStd5rBfGWFOE=";
})
(fetchNuGet {
pname = "System.Security.Principal.Windows";
version = "4.5.0";
hash = "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY=";
})
(fetchNuGet {
pname = "System.Text.Encodings.Web";
version = "7.0.0";
hash = "sha256-tF8qt9GZh/nPy0mEnj6nKLG4Lldpoi/D8xM5lv2CoYQ=";
})
(fetchNuGet {
pname = "System.Text.Json";
version = "7.0.3";
hash = "sha256-aSJZ17MjqaZNQkprfxm/09LaCoFtpdWmqU9BTROzWX4=";
})
]