├── .all-contributorsrc
├── .config
└── dotnet-tools.json
├── .editorconfig
├── .gitattributes
├── .github
├── CODEOWNERS
├── dependabot.yml
├── labeler.yml
├── release.yml
└── workflows
│ ├── build-test-pack.yml
│ ├── codeql-analysis.yml
│ ├── label-pull-requests.yml
│ └── release.yml
├── .gitignore
├── .globalconfig
├── CHANGELOG.md
├── Common.props
├── Directory.Build.props
├── Directory.Build.targets
├── Directory.Packages.props
├── LICENSE
├── NuGet-README.md
├── NuGet.config
├── PolyKit.sln
├── PolyKit.sln.DotSettings
├── README.md
├── THIRD-PARTY-NOTICES
├── build.cake
├── build
├── BuildData.cake
├── Changelog.cake
├── DocFx.cake
├── THIRD-PARTY-NOTICES
├── dotnet.cake
├── environment.cake
├── fail.cake
├── filesystem.cake
├── git.cake
├── github.cake
├── json.cake
├── nbgv.cake
├── options.cake
├── process.cake
├── public-api.cake
├── setup-teardown.cake
├── utilities.cake
├── versioning.cake
└── workspace.cake
├── global.json
├── graphics
├── PackageIcon.png
├── README.md
├── Readme.png
├── Readme.svg
├── SocialCard.png
├── SocialCard.svg
├── SquareLogo.svg
└── docs
│ ├── favicon.ico
│ └── logo.svg
├── src
├── PolyKit.Embedded
│ ├── PolyKit.Embedded.csproj
│ └── build
│ │ └── PolyKit.Embedded.targets
├── PolyKit.Generator
│ ├── PolyKit.Generator.csproj
│ └── PolyfillGenerator.cs
├── PolyKit.Polyfills
│ ├── PolyKit.Polyfills.csproj
│ ├── PolyKit
│ │ └── Diagnostics
│ │ │ └── CodeAnalysis
│ │ │ └── ValidatedNotNullAttribute.cs
│ └── System
│ │ ├── DateOnly.cs
│ │ ├── Diagnostics
│ │ ├── CodeAnalysis
│ │ │ ├── AllowNullAttribute.cs
│ │ │ ├── ConstantExpectedAttribute.cs
│ │ │ ├── DisallowNullAttribute.cs
│ │ │ ├── DoesNotReturnAttribute.cs
│ │ │ ├── DoesNotReturnIfAttribute.cs
│ │ │ ├── DynamicDependencyAttribute.cs
│ │ │ ├── DynamicallyAccessedMemberTypes.cs
│ │ │ ├── DynamicallyAccessedMembersAttribute.cs
│ │ │ ├── ExperimentalAttribute.cs
│ │ │ ├── MaybeNullAttribute.cs
│ │ │ ├── MaybeNullWhenAttribute.cs
│ │ │ ├── MemberNotNullAttribute.cs
│ │ │ ├── MemberNotNullWhenAttribute.cs
│ │ │ ├── NotNullAttribute.cs
│ │ │ ├── NotNullIfNotNullAttribute.cs
│ │ │ ├── NotNullWhenAttribute.cs
│ │ │ ├── RequiresAssemblyFilesAttribute.cs
│ │ │ ├── RequiresDynamicCodeAttribute.cs
│ │ │ ├── RequiresUnreferencedCodeAttribute.cs
│ │ │ ├── SetsRequiredMembersAttribute.cs
│ │ │ ├── StringSyntaxAttribute.cs
│ │ │ ├── UnconditionalSuppressMessageAttribute.cs
│ │ │ └── UnscopedRefAttribute.cs
│ │ ├── PolyKitStackTraceExtensions.cs
│ │ ├── StackTraceHiddenAttribute.cs
│ │ └── TraceFormat.cs
│ │ ├── HashCode.cs
│ │ ├── ISpanFormattable.cs
│ │ ├── Index.cs
│ │ ├── Linq
│ │ └── PolyKitEnumerable.cs
│ │ ├── PolyKitExceptionExtensions.cs
│ │ ├── Range.cs
│ │ ├── Runtime
│ │ ├── CompilerServices
│ │ │ ├── AsyncMethodBuilderAttribute.cs
│ │ │ ├── CallerArgumentExpressionAttribute.cs
│ │ │ ├── CompilerFeatureRequiredAttribute.cs
│ │ │ ├── InterpolatedStringHandlerArgumentAttribute.cs
│ │ │ ├── InterpolatedStringHandlerAttribute.cs
│ │ │ ├── IsExternalInit.cs
│ │ │ ├── ModuleInitializerAttribute.cs
│ │ │ ├── RequiredMemberAttribute.cs
│ │ │ └── SkipLocalsInitAttribute.cs
│ │ ├── InteropServices
│ │ │ └── UnmanagedCallersOnlyAttribute.cs
│ │ └── Versioning
│ │ │ └── RequiresPreviewFeaturesAttribute.cs
│ │ └── TimeOnly.cs
└── PolyKit
│ └── PolyKit.csproj
├── stylecop.json
└── version.json
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "PolyKit",
3 | "projectOwner": "Tenacom",
4 | "repoType": "github",
5 | "repoHost": "https://github.com",
6 | "files": [
7 | "README.md"
8 | ],
9 | "imageSize": 100,
10 | "commit": true,
11 | "commitConvention": "jshint",
12 | "contributorsPerLine": 7,
13 | "contributorsSortAlphabetically": true,
14 | "badgeTemplate": "[](#contributors)",
15 | "contributorTemplate": "\">
\" width=\"<%= options.imageSize %>px;\" alt=\"\"/>
<%= contributor.name %>",
16 | "types": {
17 | "custom": {}
18 | },
19 | "linkToUsage": true,
20 | "skipCi": true,
21 | "contributors": [
22 | {
23 | "login": "rdeago",
24 | "name": "Riccardo De Agostini",
25 | "avatar_url": "https://avatars.githubusercontent.com/u/139223?v=4",
26 | "profile": "https://github.com/rdeago",
27 | "contributions": [
28 | "doc",
29 | "code",
30 | "projectManagement",
31 | "ideas",
32 | "maintenance",
33 | "question",
34 | "review"
35 | ]
36 | }
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "cake.tool": {
6 | "version": "4.0.0",
7 | "commands": [
8 | "dotnet-cake"
9 | ]
10 | },
11 | "nbgv": {
12 | "version": "3.6.133",
13 | "commands": [
14 | "nbgv"
15 | ]
16 | },
17 | "dotnet-reportgenerator-globaltool": {
18 | "version": "5.2.0",
19 | "commands": [
20 | "reportgenerator"
21 | ]
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # IMPORTANT: Always keep EOL settings in sync with .editorconfig
2 |
3 | # Default settings
4 | * text=auto
5 |
6 | # Solution files
7 | *.sln text eol=crlf
8 |
9 | # Code files
10 | *.cake text eol=crlf diff=csharp
11 | *.cs text eol=crlf diff=csharp
12 | *.vb text eol=crlf
13 |
14 | # XML project files
15 | *.csproj text eol=lf
16 | *.vbproj text eol=lf
17 | *.vcxproj text eol=lf
18 | *.vcxproj.filters text eol=lf
19 | *.proj text eol=lf
20 | *.projitems text eol=lf
21 | *.shproj text eol=lf
22 | *.props text eol=lf
23 | *.targets text eol=lf
24 |
25 | # XML config files
26 | *.ruleset text eol=lf
27 | *.config text eol=lf
28 | *.nuspec text eol=lf
29 | *.resx text eol=lf
30 | *.vsixmanifest text eol=lf
31 | *.vsct text eol=lf
32 | *.runsettings text eol=lf
33 |
34 | # Other XML files
35 | *.xml text eol=lf
36 | *.svg text eol=lf
37 |
38 | # JSON files
39 | *.json text eol=lf
40 |
41 | # YAML files
42 | *.yml text eol=lf
43 | *.yaml text eol=lf
44 |
45 | # Shell scripts
46 | *.in text eol=lf diff=bash
47 | *.sh text eol=lf diff=bash
48 |
49 | # Windows batch files
50 | *.bat text eol=crlf
51 | *.BAT text eol=crlf
52 | *.cmd text eol=crlf
53 | *.CMD text eol=crlf
54 |
55 | # Markdown files
56 | *.md text eol=lf diff=markdown
57 |
58 | # InnoSetup files
59 | *.iss text eol=crlf
60 |
61 | # Image files
62 | *.jpg binary
63 | *.png binary
64 | *.gif binary
65 |
66 | # Document files
67 | *.pdf binary diff=astextplain
68 | *.PDF binary diff=astextplain
69 | *.rtf binary diff=astextplain
70 | *.RTF binary diff=astextplain
71 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # This file specifies users whose review is automatically requested when a PR modifies certain files.
2 | # For more ionformation see:
3 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
4 |
5 | # GitHub and apps configuration files
6 | /.github/ @rdeago
7 | /.all-contributorsrc @rdeago
8 |
9 | # Git configuration files
10 | /.git* @rdeago
11 |
12 | # Build scripts
13 | *.cake @rdeago
14 |
15 | # Licensing
16 | LICENSE @rdeago
17 | THIRD-PARTY-NOTICES @rdeago
18 |
19 | # Solution infrastructure files
20 | Directory.Build.* @rdeago
21 | .editorconfig @rdeago
22 | .globalconfig @rdeago
23 | stylecop.json @rdeago
24 | *.DotSettings @rdeago
25 | NuGet.config @rdeago
26 | version.json @rdeago
27 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule: { interval: "daily" }
6 | labels: [ "area:deps", "area:ci" ]
7 | reviewers: [ "rdeago" ]
8 | - package-ecosystem: "nuget"
9 | directory: "/"
10 | schedule: { interval: "daily" }
11 | labels: [ "area:deps" ]
12 | reviewers: [ "rdeago" ]
13 |
--------------------------------------------------------------------------------
/.github/labeler.yml:
--------------------------------------------------------------------------------
1 | 'area:code':
2 | - '*.sln'
3 | - 'src/**/*'
4 |
5 | 'area:style':
6 | - '**/.editorconfig'
7 | - '**/.globalconfig'
8 | - '**/stylecop.json'
9 | - '**/*.DotSettings'
10 |
11 | 'area:build':
12 | - '**/*.cake'
13 | - 'build/**/*'
14 |
15 | 'area:repo':
16 | - '.github/*.yml'
17 | - '.github/**/*.md'
18 | - CODEOWNERS
19 | - '.github/CODEOWNERS'
20 |
21 | 'area:ci':
22 | - '.github/workflows/**/*'
23 | - 'lgtm.yml'
24 |
25 | 'area:deps':
26 | - '**/Directory.Packages.props'
27 | - Directory.Build.props
28 | - Directory.Build.targets
29 | - global.json
30 | - .config/dotnet-tools.json
31 |
32 | 'area:docs':
33 | - 'docs/**/*'
34 | - '.all-contributorsrc'
35 | - '**/CHANGELOG.md'
36 | - '**/LICENSE'
37 | - '**/NuGet-README.md'
38 | - '**/README.md'
39 | - '**/THIRD-PARTY-NOTICES'
40 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | exclude:
3 | labels:
4 | - ignore-for-release
5 | categories:
6 | - title: Breaking changes
7 | labels:
8 | - breaking
9 | - title: New features
10 | labels:
11 | - enhancement
12 | - title: Bugs fixed
13 | labels:
14 | - bug
15 | - title: Other changes
16 | labels:
17 | - "*"
18 |
--------------------------------------------------------------------------------
/.github/workflows/build-test-pack.yml:
--------------------------------------------------------------------------------
1 | name: Build, test, and pack
2 |
3 | on:
4 | push:
5 | branches: [ main, 'v[0-9]+.[0-9]+' ]
6 | pull_request:
7 | branches: [ main, 'v[0-9]+.[0-9]+' ]
8 |
9 | jobs:
10 | build_test_pack:
11 | runs-on: windows-latest
12 | env:
13 | DOTNET_NOLOGO: 'true'
14 | DOTNET_CLI_TELEMETRY_OPTOUT: 'true'
15 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true'
16 | DOTNET_CLI_UI_LANGUAGE: 'en-US'
17 | FEEDZ_IO_PRIVATE_TOKEN: ${{ secrets.FEEDZ_IO_PRIVATE_TOKEN }}
18 | steps:
19 | - name: Checkout repository with full history
20 | uses: actions/checkout@v4
21 | with:
22 | fetch-depth: 0 # Checkout with full history so nbgv can compute Git height correctly.
23 | - name: Setup .NET SDK
24 | uses: actions/setup-dotnet@v3
25 | with:
26 | global-json-file: global.json
27 | - name: Restore .NET tools
28 | shell: cmd
29 | run: dotnet tool restore
30 | - name: Run build script
31 | shell: cmd
32 | run: |
33 | if [%CAKE_VERBOSITY%]==[] set CAKE_VERBOSITY=Normal
34 | if [%RUNNER_DEBUG%]==[1] set CAKE_VERBOSITY=Diagnostic
35 | dotnet cake --target Pack --verbosity %CAKE_VERBOSITY%
36 | - name: Upload coverage to Codecov
37 | uses: codecov/codecov-action@v3
38 | with:
39 | working-directory: ./TestResults/
40 | files: Cobertura.xml
41 | verbose: true
42 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [ main, 'v[0-9]+.[0-9]+' ]
6 | pull_request:
7 | branches: [ main, 'v[0-9]+.[0-9]+' ]
8 | schedule:
9 | - cron: '38 16 * * 6' # At 4:38PM, every Saturday
10 |
11 | jobs:
12 | analyze:
13 | name: Analyze
14 | runs-on: ubuntu-latest
15 | env:
16 | DOTNET_NOLOGO: 'true'
17 | DOTNET_CLI_TELEMETRY_OPTOUT: 'true'
18 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true'
19 | DOTNET_CLI_UI_LANGUAGE: 'en-US'
20 | permissions:
21 | actions: read
22 | contents: read
23 | security-events: write
24 | strategy:
25 | fail-fast: false
26 | matrix:
27 | language: [ 'csharp' ] # https://aka.ms/codeql-docs/language-support
28 | steps:
29 | - name: Checkout repository with full history
30 | uses: actions/checkout@v4
31 | with:
32 | fetch-depth: 0 # Checkout with full history so nbgv can compute Git height correctly.
33 | - name: Initialize CodeQL
34 | uses: github/codeql-action/init@v2
35 | with:
36 | languages: ${{ matrix.language }}
37 | queries: security-and-quality
38 | - name: Setup .NET SDK
39 | uses: actions/setup-dotnet@v3
40 | with:
41 | global-json-file: global.json
42 | - name: Restore .NET tools
43 | run: dotnet tool restore
44 | - name: Build solution
45 | run: |
46 | if test "$RUNNER_DEBUG" == "1"; then
47 | CAKE_VERBOSITY="Diagnostic"
48 | elif test -z "$CAKE_VERBOSITY"; then
49 | CAKE_VERBOSITY="Normal"
50 | fi
51 | dotnet cake --target Build --verbosity $CAKE_VERBOSITY
52 | - name: Perform CodeQL Analysis
53 | uses: github/codeql-action/analyze@v2
54 | with:
55 | category: "/language:${{matrix.language}}"
56 |
--------------------------------------------------------------------------------
/.github/workflows/label-pull-requests.yml:
--------------------------------------------------------------------------------
1 | name: Set labels on PR
2 | on:
3 | pull_request_target:
4 | types: [ opened, synchronize, reopened ]
5 |
6 | jobs:
7 |
8 | set_labels:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | contents: read
12 | pull-requests: write
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v4
16 | - name: Assign labels to pull request
17 | uses: actions/labeler@v4
18 | with:
19 | repo-token: "${{ secrets.GITHUB_TOKEN }}"
20 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Publish a release
2 |
3 | concurrency:
4 | group: release-${{ github.ref }}
5 | cancel-in-progress: true
6 |
7 | on:
8 | workflow_dispatch:
9 | inputs:
10 | versionSpecChange:
11 | description: 'Version spec change'
12 | required: true
13 | type: choice
14 | default: 'None'
15 | options:
16 | - None
17 | - Unstable
18 | - Stable
19 | - Minor
20 | - Major
21 | checkPublicApi:
22 | description: 'Check public API files'
23 | required: false
24 | default: true
25 | type: boolean
26 | forceUpdateChangelog:
27 | description: 'Update changelog on preview'
28 | required: false
29 | default: false
30 | type: boolean
31 | checkChangelog:
32 | description: 'Check changelog before update'
33 | required: false
34 | default: true
35 | type: boolean
36 | cakeVerbosity:
37 | description: 'Cake verbosity'
38 | required: true
39 | type: choice
40 | default: 'Normal'
41 | options:
42 | - Normal
43 | - Verbose
44 | - Diagnostic
45 | jobs:
46 | release:
47 | runs-on: windows-latest
48 | env:
49 | DOTNET_NOLOGO: 'true'
50 | DOTNET_CLI_TELEMETRY_OPTOUT: 'true'
51 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true'
52 | DOTNET_CLI_UI_LANGUAGE: 'en-US'
53 | FEEDZ_IO_PRIVATE_TOKEN: ${{ secrets.FEEDZ_IO_PRIVATE_TOKEN }}
54 | GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
55 |
56 | # Deploy non-prerelease public packages on NuGet
57 | RELEASE_NUGET_SOURCE: 'https://api.nuget.org/v3/index.json'
58 | RELEASE_NUGET_KEY: ${{ secrets.NUGET_DEPLOYMENT_KEY }}
59 | # Deploy prerelease public packages on a public Feedz.io feed
60 | PRERELEASE_NUGET_SOURCE: 'https://f.feedz.io/tenacom/preview/nuget/index.json'
61 | PRERELEASE_NUGET_KEY: ${{ secrets.FEEDZ_IO_PRIVATE_TOKEN }}
62 | # Deploy all private packages on a private Feedz.io feed
63 | PRIVATE_NUGET_SOURCE: 'https://f.feedz.io/tenacom/private/nuget/index.json'
64 | PRIVATE_NUGET_KEY: ${{ secrets.FEEDZ_IO_PRIVATE_TOKEN }}
65 |
66 | VERSION_SPEC_CHANGE: ${{ inputs.versionSpecChange }}
67 | CHECK_PUBLIC_API: ${{ inputs.checkPublicApi }}
68 | FORCE_UPDATE_CHANGELOG: ${{ inputs.forceUpdateChangelog }}
69 | CHECK_CHANGELOG: ${{ inputs.checkChangelog }}
70 | CAKE_VERBOSITY: ${{ inputs.cakeVerbosity }}
71 | steps:
72 | - name: Log workflow inputs
73 | shell: cmd
74 | run: |
75 | echo Version spec change : %VERSION_SPEC_CHANGE%
76 | echo Check public API files : %CHECK_PUBLIC_API%
77 | echo Update changelog on preview : %FORCE_UPDATE_CHANGELOG%
78 | echo Check changelog before update : %CHECK_CHANGELOG%
79 | echo Cake verbosity : %CAKE_VERBOSITY%
80 | - name: Checkout repository with full history
81 | uses: actions/checkout@v4
82 | with:
83 | fetch-depth: 0 # Checkout with full history so nbgv can compute Git height correctly.
84 | token: ${{ secrets.RELEASE_TOKEN }}
85 | persist-credentials: true # We need auth set up in the Cake script
86 | - name: Setup .NET SDK
87 | uses: actions/setup-dotnet@v3
88 | with:
89 | global-json-file: global.json
90 | - name: Restore .NET tools
91 | shell: cmd
92 | run: dotnet tool restore
93 | - name: Run build script
94 | id: build
95 | shell: cmd
96 | run: |
97 | if [%CAKE_VERBOSITY%]==[] set CAKE_VERBOSITY=Normal
98 | if [%RUNNER_DEBUG%]==[1] set CAKE_VERBOSITY=Diagnostic
99 | dotnet cake --target Release --verbosity %CAKE_VERBOSITY%
100 | - name: Upload coverage to Codecov
101 | uses: codecov/codecov-action@v3
102 | with:
103 | working-directory: ./TestResults/
104 | files: Cobertura.xml
105 | name: v${{ steps.build.outputs.version }}
106 | verbose: true
107 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build artifacts
2 | artifacts/
3 |
4 | # Local build logs
5 | logs/
6 |
7 | # Cake build
8 | tools/
9 |
10 | # Testing
11 | TestResults/
12 |
13 | # Visual Studio
14 | **/bin/
15 | **/obj/
16 | **/.vs/
17 | *.csproj.user
18 | *.pubxml.user
19 |
20 | # ReSharper
21 | *.DotSettings.user
22 | _ReSharper.*/
23 |
24 | # Windows thumbnails
25 | Thumbs.db
26 |
27 | # DocFx
28 | docs/globalMetadata.json
29 | docs/api/.manifest
30 | docs/api/*.yml
31 | docs/obj/
32 | docs/_site/
33 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to PolyKit will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## Unreleased changes
9 |
10 | ### New features
11 |
12 | ### Changes to existing features
13 |
14 | ### Bugs fixed in this release
15 |
16 | ### Known problems introduced by this release
17 |
18 | ## [3.0.9](https://github.com/Tenacom/PolyKit/releases/tag/3.0.9) (2023-11-26)
19 |
20 | This release updates some dependencies to their post-.NET 8.0 versions. No other modifications were made.
21 |
22 | ## [3.0.4](https://github.com/Tenacom/PolyKit/releases/tag/3.0.4) (2023-11-20)
23 |
24 | ### New features
25 |
26 | - .NET 8 was added as a target platform.
27 | - All polyfills were updated with modifications (if any) made to BCL types up to the release of .NET 8.0.0.
28 | - The polyfill for [`ExperimentalAttribute`](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.experimentalattribute) has been added; however, this attribute is only polyfilled by PolyKit.Embedded when compiling with .NET SDK 8.0. This avoids giving the user the false impression that the attribute is supported, when the compiler doesn't actually support it.
29 | - [`DateOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.dateonly) and [`TimeOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.timeonly) polyfills now support [`deconstruction`](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/deconstruct).
30 |
31 | ### Changes to existing features
32 |
33 | - **BREAKING CHANGE:** Extension classes that were previously in `PolyKit.*` namespaces have been moved to `System.*` namespaces, in order for their members to be more easily discoverable (e.g. by Intellisense) and usable without additional `using` statements.
34 | This change may seem to go against best practices, as it places PolyKit types in namespaces usually reserved for the BCL; however, it makes sense if you consider that one of the purposes of polyfills is to minimize the amount of code changes necessary to backport code.
35 | Affected extension classes include:
36 | - `PolyKitEnumerable`, moved from `PolyKit.Linq` to `System.Linq`;
37 | - `PolyKitExceptionExtensions`, moved from `PolyKit.Diagnostics` to `System`;
38 | - `PolyKitStackTraceExtensions`, moved from `PolyKit.Diagnostics` to `System.Diagnostics`.
39 |
40 | ## [2.0.30](https://github.com/Tenacom/PolyKit/releases/tag/2.0.30) (2022-11-24)
41 |
42 | ### Bugs fixed in this release
43 |
44 | - The polyfill for [`DateOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.dateonly) could generate a `CS8602` warning (possible dereference of a null reference).
45 | - The polyfill for [`TimeOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.timeonly), when compiled without span support, generated two `CS1503` errors because of a missing preprocessor conditional.
46 |
47 | ## [2.0.26](https://github.com/Tenacom/PolyKit/releases/tag/2.0.26) (2022-11-24)
48 |
49 | ### Bugs fixed in this release
50 |
51 | - The polyfills for [`DateOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.dateonly) and [`TimeOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.timeonly) only worked when either the target platform supported spans, or the [`System.Memory`](https://www.nuget.org/packages/System.Memory) package was referenced.
52 |
53 | ## [2.0.24](https://github.com/Tenacom/PolyKit/releases/tag/2.0.24) (2022-11-23)
54 |
55 | ### New features
56 |
57 | - .NET 7 was added as a target platform.
58 | - Features that were introduced with .NET 7 are not polyfilled by PolyKit.Embedded when compiling with .NET SDK 6.0. This avoids giving the user the false impression that, for example, `UnscopedRefAttribute` is supported, when the compiler doesn't actually support it.
59 | - PolyKit now provides a quasi-polyfill for [`Enumerable.TryGetNonEnumeratedCount`](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.trygetnonenumeratedcount). Since extending the `Enumerable` class is not possible, PolyKit adds (in the `PolyKit.Linq` namespace) a `TryGetCountWithoutEnumerating` extension method that calls `TryGetNonEnumeratedCount` on .NET6.0+ and polyfills as much functionality as possible on older frameworks.
60 | - Polyfills for the following features were added:
61 | - [required members](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#required-members);
62 | - [`scoped` modifier](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/low-level-struct-improvements) (including the `UnscopedRef` attribute);
63 | - [`AsyncMethodBuilder` attribute](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#asyncmethodbuilder-attribute);
64 | - [`ModuleInitializer` attribute](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#moduleinitializer-attribute);
65 | - [trimming incompatibility attributes](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/prepare-libraries-for-trimming#resolve-trim-warnings);
66 | - [`UnconditionalSuppressMessage` attribute](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/prepare-libraries-for-trimming#unconditionalsuppressmessage);
67 | - [`CompilerFeatureRequired` attribute](https://github.com/dotnet/runtime/issues/66167);
68 | - [`RequiresPreviewFeatures` attribute](https://github.com/dotnet/designs/blob/main/accepted/2021/preview-features/preview-features.md);
69 | - [`UnmanagedCallersOnly` attribute](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/function-pointers#systemruntimeinteropservicesunmanagedcallersonlyattribute);
70 | - [`ConstantExpected` attribute](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.constantexpectedattribute);
71 | - [`StringSyntax` attribute](https://github.com/dotnet/runtime/issues/62505);
72 | - [`ISpanFormattable` interface](https://learn.microsoft.com/en-us/dotnet/api/system.ispanformattable) (note that the polyfill does NOT add `ISpanFormattable` support to .NET Runtime types);
73 | - [`DateOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.dateonly) and [`TimeOnly`](https://learn.microsoft.com/en-us/dotnet/api/system.timeonly) structs (not that the polyfills do NOT implement [`IParsable`](https://learn.microsoft.com/en-us/dotnet/api/system.iparsable) and [`ISpanParsable`](https://learn.microsoft.com/en-us/dotnet/api/system.ispanparsable-1), although the methods are there and can be used as public methods of the individual types).
74 |
75 | ### Changes to existing features
76 |
77 | - **BREAKING CHANGE:** Following .NET's [Library support for older frameworks](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/7.0/old-framework-support) policy, support for .NET Core 3.1 has been removed.
78 | - All types provideed by PolyKit are now flagged with the necessary attributes to be ignored by code analyzers, debuggers, code coverage tools, code metrics, etc. See [this blog post](https://riccar.do/posts/2022/2022-05-30-well-behaved-guest-code.html) for more information about the attributes added to types and the rationale behind each of them.
79 |
80 | ## [1.0.16](https://github.com/Tenacom/PolyKit/releases/tag/1.0.16) (2022-11-01)
81 |
82 | Initial release.
83 |
--------------------------------------------------------------------------------
/Common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PolyKit
6 | Tenacom and contributors
7 | Tenacom
8 | Tenacom
9 | Copyright (c) $(Authors)
10 |
11 | false
12 | https://github.com/Tenacom/PolyKit
13 | See $(PackageProjectUrl)/blob/main/CHANGELOG.md
14 | https://github.com/Tenacom/PolyKit
15 | true
16 | true
17 | true
18 | true
19 | false
20 |
21 |
22 |
23 |
24 | latest
25 | false
26 | true
27 | enable
28 | true
29 | true
30 | false
31 | true
32 | false
33 | true
34 | false
35 |
36 |
37 |
38 |
39 | false
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Tenacom and contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/NuGet-README.md:
--------------------------------------------------------------------------------
1 | # 
2 |
3 | ---
4 |
5 | PolyKit is both a run-time library (provided via the [`PolyKit`](https://nuget.org/packages/PolyKit) NuGet package) and a set of ready-to-compile source files (provided via the [`PolyKit.Embedded`](https://nuget.org/packages/PolyKit.Embedded) NuGet package) that add support for latest C# features as well as recent additions to the .NET runtime library, even in projects targeting .NET Framework or .NET Standard 2.0.
6 |
7 | Want to know more? [Here's the complete README.](https://github.com/Tenacom/PolyKit#readme)
8 |
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/PolyKit.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.2.32526.322
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "- Configuration", "- Configuration", "{ED7AE9DE-0190-495E-BAB8-91D7916DE79B}"
7 | ProjectSection(SolutionItems) = preProject
8 | .editorconfig = .editorconfig
9 | .globalconfig = .globalconfig
10 | Common.props = Common.props
11 | NuGet.config = NuGet.config
12 | stylecop.json = stylecop.json
13 | version.json = version.json
14 | EndProjectSection
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "- Documentation", "- Documentation", "{0661C764-ED18-47F2-8A94-8193D0652E8A}"
17 | ProjectSection(SolutionItems) = preProject
18 | CHANGELOG.md = CHANGELOG.md
19 | LICENSE = LICENSE
20 | NuGet-README.md = NuGet-README.md
21 | README.md = README.md
22 | THIRD-PARTY-NOTICES = THIRD-PARTY-NOTICES
23 | EndProjectSection
24 | EndProject
25 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04BEFF7A-9805-4109-983D-F1832FC44532}"
26 | EndProject
27 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PolyKit", "src\PolyKit\PolyKit.csproj", "{9A8C068C-0751-4E2B-ABEB-D3E3C9DD1FB4}"
28 | EndProject
29 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PolyKit.Embedded", "src\PolyKit.Embedded\PolyKit.Embedded.csproj", "{CAB8EAA2-8652-4993-ACA5-6693CE4D4A26}"
30 | EndProject
31 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PolyKit.Polyfills", "src\PolyKit.Polyfills\PolyKit.Polyfills.csproj", "{A977FFFD-8B8C-4AAC-9176-8976960DE5C4}"
32 | EndProject
33 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PolyKit.Generator", "src\PolyKit.Generator\PolyKit.Generator.csproj", "{9CE09A81-98CF-4CC2-B5FE-8159AA933F36}"
34 | EndProject
35 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "- Dependencies", "- Dependencies", "{8474FA20-638B-49BB-BF75-AAFC78B60750}"
36 | ProjectSection(SolutionItems) = preProject
37 | Directory.Packages.props = Directory.Packages.props
38 | .config\dotnet-tools.json = .config\dotnet-tools.json
39 | global.json = global.json
40 | EndProjectSection
41 | EndProject
42 | Global
43 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
44 | Debug|Any CPU = Debug|Any CPU
45 | Release|Any CPU = Release|Any CPU
46 | EndGlobalSection
47 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
48 | {9A8C068C-0751-4E2B-ABEB-D3E3C9DD1FB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {9A8C068C-0751-4E2B-ABEB-D3E3C9DD1FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {9A8C068C-0751-4E2B-ABEB-D3E3C9DD1FB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {9A8C068C-0751-4E2B-ABEB-D3E3C9DD1FB4}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {CAB8EAA2-8652-4993-ACA5-6693CE4D4A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {CAB8EAA2-8652-4993-ACA5-6693CE4D4A26}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {CAB8EAA2-8652-4993-ACA5-6693CE4D4A26}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {CAB8EAA2-8652-4993-ACA5-6693CE4D4A26}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {A977FFFD-8B8C-4AAC-9176-8976960DE5C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57 | {A977FFFD-8B8C-4AAC-9176-8976960DE5C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
58 | {A977FFFD-8B8C-4AAC-9176-8976960DE5C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
59 | {A977FFFD-8B8C-4AAC-9176-8976960DE5C4}.Release|Any CPU.Build.0 = Release|Any CPU
60 | {9CE09A81-98CF-4CC2-B5FE-8159AA933F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {9CE09A81-98CF-4CC2-B5FE-8159AA933F36}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {9CE09A81-98CF-4CC2-B5FE-8159AA933F36}.Release|Any CPU.ActiveCfg = Release|Any CPU
63 | {9CE09A81-98CF-4CC2-B5FE-8159AA933F36}.Release|Any CPU.Build.0 = Release|Any CPU
64 | EndGlobalSection
65 | GlobalSection(SolutionProperties) = preSolution
66 | HideSolutionNode = FALSE
67 | EndGlobalSection
68 | GlobalSection(NestedProjects) = preSolution
69 | {9A8C068C-0751-4E2B-ABEB-D3E3C9DD1FB4} = {04BEFF7A-9805-4109-983D-F1832FC44532}
70 | {CAB8EAA2-8652-4993-ACA5-6693CE4D4A26} = {04BEFF7A-9805-4109-983D-F1832FC44532}
71 | {A977FFFD-8B8C-4AAC-9176-8976960DE5C4} = {04BEFF7A-9805-4109-983D-F1832FC44532}
72 | {9CE09A81-98CF-4CC2-B5FE-8159AA933F36} = {04BEFF7A-9805-4109-983D-F1832FC44532}
73 | EndGlobalSection
74 | GlobalSection(ExtensibilityGlobals) = postSolution
75 | SolutionGuid = {C9053E59-317D-43DC-A16B-6E45E036C77E}
76 | EndGlobalSection
77 | EndGlobal
78 |
--------------------------------------------------------------------------------
/build/DocFx.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #tool nuget:?package=docfx.console&version=2.59.4
5 |
6 | #nullable enable
7 |
8 | // ---------------------------------------------------------------------------------------------
9 | // DocFx class
10 | // ---------------------------------------------------------------------------------------------
11 |
12 | using System;
13 | using System.Runtime.InteropServices;
14 |
15 | /*
16 | * Summary : Implements DocFx operations
17 | */
18 | sealed class DocFx
19 | {
20 | private const string ToolExeName = "docfx.exe";
21 |
22 | private readonly DirectoryPath _docsPath;
23 | private FilePath? _docFxPath;
24 |
25 | /*
26 | * Summary : Initializes a new instance of the DocFx class.
27 | * Params : context - The Cake context.
28 | * docsPath - The path to the folder where DocFX operates.
29 | */
30 | public DocFx(ICakeContext context, BuildData buildData, DirectoryPath docsPath)
31 | {
32 | Context = context;
33 | BuildData = buildData;
34 | _docsPath = docsPath;
35 | }
36 |
37 | private ICakeContext Context { get; }
38 |
39 | private BuildData BuildData { get; }
40 |
41 | /*
42 | * Summary : Extracts language metadata according to docfx.json settings.
43 | */
44 | public void Metadata()
45 | {
46 | var docFxJsonPath = _docsPath.CombineWithFilePath("docfx.json");
47 | var json = LoadJsonObject(docFxJsonPath);
48 | if (!json.TryGetPropertyValue("metadata", out _))
49 | {
50 | Context.Information("No metadata to generate.");
51 | return;
52 | }
53 |
54 | Context.Information("Running DocFx...");
55 | Run("metadata");
56 | }
57 |
58 | /*
59 | * Summary : Generates documentation according to docfx.json settings.
60 | */
61 | public void Build()
62 | {
63 | Context.Information("Running DocFx...");
64 | Run("build");
65 | }
66 |
67 | /*
68 | * Summary : Hosts the built documentation web site.
69 | */
70 | public void Serve()
71 | {
72 | if (BuildData.IsCI)
73 | {
74 | Context.Information("DocFX web server not suitable for cloud builds, skipping.");
75 | return;
76 | }
77 |
78 | Context.Information("Starting DocFX web server...");
79 | var (_, process) = Start("serve _site");
80 | Console.WriteLine("Press any key to stop serving...");
81 | _ = WaitForKey();
82 | Context.Information("Stopping DocFX web server...");
83 | process.Kill();
84 | process.WaitForExit();
85 | }
86 |
87 | private static ConsoleKeyInfo WaitForKey()
88 | {
89 | while (Console.KeyAvailable)
90 | {
91 | _ = Console.ReadKey(true);
92 | }
93 |
94 | return Console.ReadKey(true);
95 | }
96 |
97 | private void Run(ProcessArgumentBuilder arguments)
98 | {
99 | var (commandName, process) = Start(arguments);
100 | process.WaitForExit();
101 | var exitCode = process.GetExitCode();
102 | Context.Ensure(exitCode == 0, $"{commandName} exited with code {exitCode}.");
103 | }
104 |
105 | private (string commandName, IProcess Process) Start(ProcessArgumentBuilder arguments)
106 | {
107 | _docFxPath ??= Context.Tools.Resolve(ToolExeName);
108 | Context.Ensure(_docFxPath != null, $"Cannot find {ToolExeName}");
109 | FilePath command = _docFxPath;
110 | if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
111 | {
112 | command = "mono";
113 | arguments = arguments.PrependQuoted(_docFxPath.FullPath);
114 | }
115 |
116 | var process = Context.StartAndReturnProcess(command, new ProcessSettings()
117 | {
118 | Arguments = arguments,
119 | WorkingDirectory = _docsPath,
120 | });
121 |
122 | return (command.GetFilenameWithoutExtension().ToString(), process);
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/build/THIRD-PARTY-NOTICES:
--------------------------------------------------------------------------------
1 | These scripts may use and/or incorporate third-party libraries or other resources
2 | that may be distributed under licenses different than this project.
3 |
4 | In the event that we accidentally failed to list a required notice, please
5 | bring it to our attention. Either post an issue, or email us:
6 |
7 | info@tenacom.it
8 |
9 | The attached notices are provided for information only.
10 |
11 | ================================================================================================
12 | Humanizer - https://github.com/Humanizr/Humanizer
13 | ------------------------------------------------------------------------------------------------
14 | The MIT License (MIT)
15 |
16 | Copyright (c) .NET Foundation and Contributors
17 |
18 | Permission is hereby granted, free of charge, to any person obtaining a copy
19 | of this software and associated documentation files (the "Software"), to deal
20 | in the Software without restriction, including without limitation the rights
21 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | copies of the Software, and to permit persons to whom the Software is
23 | furnished to do so, subject to the following conditions:
24 |
25 | The above copyright notice and this permission notice shall be included in
26 | all copies or substantial portions of the Software.
27 |
28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34 | THE SOFTWARE.
35 |
--------------------------------------------------------------------------------
/build/dotnet.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // .NET SDK helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System.IO;
11 | using System.Linq;
12 |
13 | using SysDirectory = System.IO.Directory;
14 | using SysPath = System.IO.Path;
15 |
16 | /*
17 | * Summary : Restore all NuGet packages for the solution.
18 | * Params : context - The Cake context.
19 | * data - Build configuration data.
20 | */
21 | static void RestoreSolution(this ICakeContext context, BuildData data)
22 | {
23 | context.Information("Restoring NuGet packages for solution...");
24 | context.DotNetRestore(data.SolutionPath.FullPath, new() {
25 | MSBuildSettings = data.MSBuildSettings,
26 | DisableParallel = true,
27 | Interactive = false,
28 | });
29 | }
30 |
31 | /*
32 | * Summary : Build all projects in the solution.
33 | * Params : context - The Cake context.
34 | * data - Build configuration data.
35 | * restore - true to restore NuGet packages before building, false otherwise.
36 | */
37 | static void BuildSolution(this ICakeContext context, BuildData data, bool restore)
38 | {
39 | context.Information($"Building solution (restore = {restore})...");
40 | context.DotNetBuild(data.SolutionPath.FullPath, new() {
41 | Configuration = data.Configuration,
42 | MSBuildSettings = data.MSBuildSettings,
43 | NoLogo = true,
44 | NoRestore = !restore,
45 | });
46 | }
47 |
48 | /*
49 | * Summary : Run all unit tests for the solution.
50 | * Params : context - The Cake context.
51 | * data - Build configuration data.
52 | * restore - true to restore NuGet packages before testing, false otherwise.
53 | * build - true to build the solution before testing, false otherwise.
54 | * collect - true to collect coverage data with Coverlet
55 | * Remarks : If successful, this method will merge all coverage reports generated by VSTest
56 | * into a single file suitable for upload to Codecov.
57 | */
58 | static void TestSolution(this ICakeContext context, BuildData data, bool restore, bool build, bool collect)
59 | {
60 | context.Information($"Running tests (restore = {restore}, build = {build}, collect = {collect})...");
61 | context.DotNetTest(data.SolutionPath.FullPath, new() {
62 | Configuration = data.Configuration,
63 | MSBuildSettings = data.MSBuildSettings,
64 | NoBuild = !build,
65 | NoLogo = true,
66 | NoRestore = !restore,
67 | ArgumentCustomization = args => collect
68 | ? args.Append("--collect:\"XPlat Code Coverage\"")
69 | : args,
70 | });
71 |
72 | // Merge coverage reports only if there are any
73 | if (collect)
74 | {
75 | if (!context.FileSystem.Exist(data.TestResultsPath) || !context.GetSubDirectories(data.TestResultsPath).Any())
76 | {
77 | context.Information("No coverage reports were generated.");
78 | }
79 | else
80 | {
81 | context.Information("Merging coverage reports...");
82 | const string CoverageDataFileName = "coverage.cobertura.xml";
83 | var coverageDataGlob = SysPath.Combine(data.TestResultsPath.FullPath, "*", CoverageDataFileName);
84 | context.DotNetTool($"reportgenerator \"-reports:{coverageDataGlob}\" \"-targetDir:{data.TestResultsPath.FullPath}\" -reporttypes:Cobertura");
85 | }
86 | }
87 | }
88 |
89 | /*
90 | * Summary : Run the Pack target on the solution. This usually produces NuGet packages,
91 | * but Buildvana SDK may hijack the target to produce, for example, setup executables.
92 | * Params : context - The Cake context.
93 | * data - Build configuration data.
94 | * restore - true to restore NuGet packages before packing, false otherwise.
95 | * build - true to build the solution before packing, false otherwise.
96 | */
97 | static void PackSolution(this ICakeContext context, BuildData data, bool restore, bool build)
98 | {
99 | context.Information($"Packing solution (restore = {restore}, build = {build})...");
100 | context.DotNetPack(data.SolutionPath.FullPath, new() {
101 | Configuration = data.Configuration,
102 | MSBuildSettings = data.MSBuildSettings,
103 | NoBuild = !build,
104 | NoLogo = true,
105 | NoRestore = !restore,
106 | });
107 | }
108 |
109 | /*
110 | * Summary : Asynchronously pushes all produced NuGet packages to the appropriate NuGet server.
111 | * Params : context - The Cake context.
112 | * data - Build configuration data.
113 | * Remarks : - This method uses the following environment variables:
114 | * * PRERELEASE_NUGET_SOURCE - NuGet source URL where to push prerelease packages
115 | * * RELEASE_NUGET_SOURCE - NuGet source URL where to push non-prerelease packages
116 | * * PRERELEASE_NUGET_KEY - API key for PRERELEASE_NUGET_SOURCE
117 | * * RELEASE_NUGET_KEY - API key for RELEASE_NUGET_SOURCE
118 | * - If there are no .nupkg files in the designated artifacts directory, this method does nothing.
119 | */
120 | static async Task NuGetPushAllAsync(this ICakeContext context, BuildData data)
121 | {
122 | const string nupkgMask = "*.nupkg";
123 | if (!SysDirectory.EnumerateFiles(data.ArtifactsPath.FullPath, nupkgMask).Any())
124 | {
125 | context.Verbose("No .nupkg files to push.");
126 | return;
127 | }
128 |
129 | var isPrivate = await context.IsPrivateRepositoryAsync(data);
130 | var nugetSource = context.GetOptionOrFail(isPrivate ? "privateNugetSource" : data.IsPrerelease ? "prereleaseNugetSource" : "releaseNugetSource");
131 | var nugetApiKey = context.GetOptionOrFail(isPrivate ? "privateNugetKey" : data.IsPrerelease ? "prereleaseNugetKey" : "releaseNugetKey");
132 | var nugetPushSettings = new DotNetNuGetPushSettings {
133 | ForceEnglishOutput = true,
134 | Source = nugetSource,
135 | ApiKey = nugetApiKey,
136 | SkipDuplicate = true,
137 | };
138 |
139 | var packages = SysPath.Combine(data.ArtifactsPath.FullPath, nupkgMask);
140 | foreach (var path in context.GetFiles(packages))
141 | {
142 | context.Information($"Pushing {path} to {nugetSource}...");
143 | context.DotNetNuGetPush(path, nugetPushSettings);
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/build/environment.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Environment helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | /*
11 | * Summary : Gets a string from the environment, failing if the value is not found or is the empty string.
12 | * Params : context - The Cake context.
13 | * name - The name of the environment variable to read.
14 | * fallbackName - The name of another environment variable to read if name is not found or its value is the empty string.
15 | * Returns : The value of an environment variable.
16 | */
17 | static string GetEnvironmentString(this ICakeContext context, string name, string fallbackName = "")
18 | {
19 | var result = context.EnvironmentVariable(name, string.Empty);
20 | if (!string.IsNullOrEmpty(result))
21 | {
22 | return result;
23 | }
24 |
25 | context.Ensure(!string.IsNullOrEmpty(fallbackName), $"Environment variable {name} is missing or has an empty value.");
26 | result = context.EnvironmentVariable(fallbackName, string.Empty);
27 | context.Ensure(!string.IsNullOrEmpty(result), 255, $"Both environment variables {name} and {fallbackName} are missing or have an empty value.");
28 | return result;
29 | }
30 |
--------------------------------------------------------------------------------
/build/fail.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Build failure helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System.Diagnostics.CodeAnalysis;
11 |
12 | /*
13 | * Summary : Fails the build with the specified message.
14 | * This method does not return.
15 | * Params : context - The Cake context.
16 | * message - A message explaining the reason for failing the build.
17 | */
18 | [DoesNotReturn]
19 | static void Fail(this ICakeContext context, string message)
20 | {
21 | context.Error(message);
22 | throw new CakeException(message);
23 | }
24 |
25 | /*
26 | * Summary : Fails the build with the specified message.
27 | * This method does not return.
28 | * Type : T - The expected return type.
29 | * Params : context - The Cake context.
30 | * message - A message explaining the reason for failing the build.
31 | * Returns : This method never returns.
32 | */
33 | [DoesNotReturn]
34 | static T Fail(this ICakeContext context, string message)
35 | {
36 | context.Error(message);
37 | throw new CakeException(message);
38 | }
39 |
40 | /*
41 | * Summary : Fails the build with the specified exit code and message.
42 | * This method does not return.
43 | * Params : context - The Cake context.
44 | * exitCode - The Cake exit code.
45 | * message - A message explaining the reason for failing the build.
46 | */
47 | [DoesNotReturn]
48 | static void Fail(this ICakeContext context, int exitCode, string message)
49 | {
50 | context.Error(message);
51 | throw new CakeException(exitCode, message);
52 | }
53 |
54 | /*
55 | * Summary : Fails the build with the specified exit code and message.
56 | * This method does not return.
57 | * Type : T - The expected return type.
58 | * Params : context - The Cake context.
59 | * exitCode - The Cake exit code.
60 | * message - A message explaining the reason for failing the build.
61 | * Returns : This method never returns.
62 | */
63 | [DoesNotReturn]
64 | static T Fail(this ICakeContext context, int exitCode, string message)
65 | {
66 | context.Error(message);
67 | throw new CakeException(exitCode, message);
68 | }
69 |
70 | /*
71 | * Summary : Fails the build with the specified message if a condition is not verified.
72 | * Params : context - The Cake context.
73 | * condition - The condition to verify.
74 | * message - A message explaining the reason for failing the build.
75 | */
76 | static void Ensure(this ICakeContext context, [DoesNotReturnIf(false)] bool condition, string message)
77 | {
78 | if (!condition)
79 | {
80 | context.Error(message);
81 | throw new CakeException(message);
82 | }
83 | }
84 |
85 | /*
86 | * Summary : Fails the build with the specified message if a condition is not verified.
87 | * Params : context - The Cake context.
88 | * condition - The condition to verify.
89 | * exitCode - The Cake exit code.
90 | * message - A message explaining the reason for failing the build.
91 | */
92 | static void Ensure(this ICakeContext context, [DoesNotReturnIf(false)] bool condition, int exitCode, string message)
93 | {
94 | if (!condition)
95 | {
96 | context.Error(message);
97 | throw new CakeException(exitCode, message);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/build/filesystem.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // File system helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | /*
11 | * Summary : Delete a directory, including its contents, if it exists.
12 | * Params : context - The Cake context.
13 | * directory - The directory to delete.
14 | */
15 | static void DeleteDirectoryIfExists(this ICakeContext context, DirectoryPath directory)
16 | {
17 | if (!context.DirectoryExists(directory))
18 | {
19 | context.Verbose($"Skipping non-existent directory: {directory}");
20 | return;
21 | }
22 |
23 | context.Information($"Deleting directory: {directory}");
24 | context.DeleteDirectory(directory, new() { Force = false, Recursive = true });
25 | }
26 |
--------------------------------------------------------------------------------
/build/git.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Git repository helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System;
11 | using System.Linq;
12 |
13 | /*
14 | * Summary : Gets the name of the current Git branch.
15 | * Params : context - The Cake context.
16 | * Returns : If HEAD is on a branch, the name of the branch; otherwise, the empty string.
17 | */
18 | static string GetCurrentGitBranch(this ICakeContext context) => context.Exec("git", "branch --show-current").FirstOrDefault(string.Empty);
19 |
20 | /*
21 | * Summary : Attempts to get information about the remote repository.
22 | * Params : context - The Cake context.
23 | * Returns : Remote - The Git remote name.
24 | * HostUrl - The base URL of the Git repository host.
25 | * Owner - The repository owner.
26 | * Name - The repository name.
27 | * Remarks : - If the githubRepository argument is given, or the GITHUB_REPOSITORY environment variable is set
28 | * (as it happens in GitHub Actions,) Owner and Name are taken from there, while Remote is set
29 | * to the first Git remote found whose fetch URL matches them.
30 | * - If GITHUB_REPOSITORY is not available, Git remote fetch URLs are parsed for Owner and Name;
31 | * remotes "upstream" and "origin" are tested, in that order, in case "origin" is a fork.
32 | */
33 | static bool TryGetRepositoryInfo(this ICakeContext context, out (string Remote, string HostUrl, string Owner, string Name) result)
34 | {
35 | return TryGetRepositoryInfoFromGitHubActions(out result)
36 | || TryGetRepositoryInfoFromGitRemote("upstream", out result)
37 | || TryGetRepositoryInfoFromGitRemote("origin", out result);
38 |
39 | bool TryGetRepositoryInfoFromGitHubActions(out (string Remote, string HostUrl, string Owner, string Name) result)
40 | {
41 | var repository = context.GetOption("githubRepository", string.Empty);
42 | if (string.IsNullOrEmpty(repository))
43 | {
44 | result = default;
45 | return false;
46 | }
47 |
48 | var hostUrl = context.GetOptionOrFail("githubServerUrl");
49 | var segments = repository.Split('/');
50 | foreach (var remote in context.Exec("git", "remote"))
51 | {
52 | if (TryGetRepositoryInfoFromGitRemote(remote, out result)
53 | && string.Equals(result.HostUrl, hostUrl, StringComparison.Ordinal)
54 | && string.Equals(result.Owner, segments[0], StringComparison.Ordinal)
55 | && string.Equals(result.Name, segments[1], StringComparison.Ordinal))
56 | {
57 | return true;
58 | }
59 | }
60 |
61 | result = default;
62 | return false;
63 | }
64 |
65 | bool TryGetRepositoryInfoFromGitRemote(string remote, out (string Remote, string HostUrl, string Owner, string Name) result)
66 | {
67 | if (context.Exec("git", "remote get-url " + remote, out var output) != 0)
68 | {
69 | result = default;
70 | return false;
71 | }
72 |
73 | var url = output.FirstOrDefault();
74 | if (string.IsNullOrEmpty(url))
75 | {
76 | result = default;
77 | return false;
78 | }
79 |
80 | Uri uri;
81 | try
82 | {
83 | uri = new Uri(url);
84 | }
85 | catch (UriFormatException)
86 | {
87 | result = default;
88 | return false;
89 | }
90 |
91 | var path = uri.AbsolutePath;
92 | path = path.EndsWith(".git", StringComparison.Ordinal)
93 | ? path.Substring(1, path.Length - 5)
94 | : path.Substring(1);
95 |
96 | var segments = path.Split('/');
97 | if (segments.Length != 2)
98 | {
99 | result = default;
100 | return false;
101 | }
102 |
103 | result = (remote, $"{uri.Scheme}://{uri.Host}{(uri.IsDefaultPort ? null : ":" + uri.Port.ToString())}", segments[0], segments[1]);
104 | return true;
105 | }
106 | }
107 |
108 | /*
109 | * Summary : Tells whether a tag exists in the local Git repository.
110 | * Params : context - The Cake context.
111 | * tag - The tag to check for.
112 | * Returns : True if the tag exists; false otherwise.
113 | */
114 | static bool GitTagExists(this ICakeContext context, string tag) => context.Exec("git", "tag").Any(s => string.Equals(tag, s, StringComparison.Ordinal));
115 |
116 | /*
117 | * Summary : Gets the latest version and the latest stable version in commit history.
118 | * Params : context - The Cake context.
119 | * Returns : A tuple of the latest version and the latest stable version;
120 | * Remarks : - If no version tag is found in commit history, this method returns a tuple of two nulls.
121 | * - If no stable version tag is found in commit history, this method returns a tuple of the latest version and null.
122 | */
123 | static (SemanticVersion? Latest, SemanticVersion? LatestStable) GitGetLatestVersions(this ICakeContext context)
124 | {
125 | context.Verbose("Looking for latest stable version tag in Git commit history...");
126 | var output = context.Exec("git", "log --pretty=format:%D");
127 | var versions = output.Where(static x => !string.IsNullOrEmpty(x))
128 | .SelectMany(static x => x.Split(", "))
129 | .Where(static x => x.StartsWith("tag: "))
130 | .Select(static x => x.Substring(5))
131 | .Select(static x => {
132 | _ = SemanticVersion.TryParse(x, out var version);
133 | return version;
134 | })
135 | .WhereNotNull();
136 |
137 | SemanticVersion? latest = null;
138 | SemanticVersion? latestStable = null;
139 | foreach (var version in versions)
140 | {
141 | if (latest == null)
142 | {
143 | latest = version;
144 | }
145 |
146 | if (!version.IsPrerelease)
147 | {
148 | latestStable = version;
149 | break;
150 | }
151 | }
152 |
153 | return (latest, latestStable);
154 | }
155 |
156 | /*
157 | * Summary : Sets Git user name and email.
158 | * Params : context - The Cake context.
159 | * name - The name of the user.
160 | * email - The email address of the user.
161 | */
162 | static void GitSetUserIdentity(this ICakeContext context, string name, string email)
163 | {
164 | context.Information($"Setting Git user name to '{name}'...");
165 | _ = context.Exec(
166 | "git",
167 | new ProcessArgumentBuilder()
168 | .Append("config")
169 | .Append("user.name")
170 | .AppendQuoted(name));
171 |
172 | context.Information($"Setting Git user email to '{email}'...");
173 | _ = context.Exec(
174 | "git",
175 | new ProcessArgumentBuilder()
176 | .Append("config")
177 | .Append("user.email")
178 | .AppendQuoted(email));
179 | }
180 |
--------------------------------------------------------------------------------
/build/json.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // JSON helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System.Text.Encodings.Web;
11 | using System.Text.Json;
12 | using System.Text.Json.Nodes;
13 |
14 | using SysFile = System.IO.File;
15 |
16 | /*
17 | * Summary : Parses a JSON object from a string. Fails the build if not successful.
18 | * Params : context - The Cake context.
19 | * str - The string to parse.
20 | * description - A description of the string for exception messages.
21 | * Returns : The parsed object.
22 | */
23 | static JsonObject ParseJsonObject(this ICakeContext context, string str, string description = "The provided string")
24 | {
25 | JsonNode? node;
26 | try
27 | {
28 | node = JsonNode.Parse(
29 | str,
30 | new JsonNodeOptions { PropertyNameCaseInsensitive = false },
31 | new JsonDocumentOptions
32 | {
33 | AllowTrailingCommas = true,
34 | CommentHandling = JsonCommentHandling.Skip,
35 | });
36 | }
37 | catch (JsonException)
38 | {
39 | context.Fail($"{description} is not valid JSON.");
40 | throw null;
41 | }
42 |
43 | return node switch {
44 | null => context.Fail($"{description} was parsed as JSON null."),
45 | JsonObject obj => obj,
46 | object other => context.Fail($"{description} was parsed as a {other.GetType().Name}, not a {nameof(JsonObject)}."),
47 | };
48 | }
49 |
50 | /*
51 | * Summary : Loads a JSON object from a file. Fails the build if not successful.
52 | * Params : context - The Cake context.
53 | * path - The path of the file to parse.
54 | * Returns : The parsed object.
55 | */
56 | static JsonObject LoadJsonObject(this ICakeContext context, FilePath path)
57 | {
58 | var fullPath = path.FullPath;
59 | JsonNode? node;
60 | try
61 | {
62 | using var stream = SysFile.OpenRead(fullPath);
63 | node = JsonNode.Parse(
64 | stream,
65 | new JsonNodeOptions { PropertyNameCaseInsensitive = false },
66 | new JsonDocumentOptions
67 | {
68 | AllowTrailingCommas = true,
69 | CommentHandling = JsonCommentHandling.Skip,
70 | });
71 | }
72 | catch (IOException e)
73 | {
74 | context.Fail($"Could not read from {fullPath}: {e.Message}");
75 | throw null;
76 | }
77 | catch (JsonException)
78 | {
79 | context.Fail($"{fullPath} does not contain valid JSON.");
80 | throw null;
81 | }
82 |
83 | return node switch {
84 | null => context.Fail($"{fullPath} was parsed as JSON null."),
85 | JsonObject obj => obj,
86 | object other => context.Fail($"{fullPath} was parsed as a {other.GetType().Name}, not a {nameof(JsonObject)}."),
87 | };
88 | }
89 |
90 | /*
91 | * Summary : Saves a JSON object to a file. Fails the build if not successful.
92 | * Params : context - The Cake context.
93 | * path - The path of the file to parse.
94 | * Returns : The parsed object.
95 | */
96 | static void SaveJson(this ICakeContext context, JsonNode json, FilePath path)
97 | {
98 | var fullPath = path.FullPath;
99 | try
100 | {
101 | using var stream = SysFile.OpenWrite(fullPath);
102 | var writerOptions = new JsonWriterOptions
103 | {
104 | Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
105 | Indented = true,
106 | };
107 |
108 | using var writer = new Utf8JsonWriter(stream, writerOptions);
109 | json.WriteTo(writer);
110 | stream.SetLength(stream.Position);
111 | }
112 | catch (IOException e)
113 | {
114 | context.Fail($"Could not write to {fullPath}: {e.Message}");
115 | throw null;
116 | }
117 | }
118 |
119 | /*
120 | * Summary : Gets the value of a property from a JSON object. Fails the build if not successful.
121 | * Types : T - The desired type of the property value.
122 | * Params : context - The Cake context.
123 | * json - The JSON object.
124 | * propertyName - The name of the property to get.
125 | * description - A description of the object for exception messages.
126 | * Returns : The value of the specified property.
127 | */
128 | static T GetJsonPropertyValue(this ICakeContext context, JsonObject json, string propertyName, string objectDescription = "JSON object")
129 | {
130 | context.Ensure(json.TryGetPropertyValue(propertyName, out var property), $"Json property {propertyName} not found in {objectDescription}.");
131 | switch (property)
132 | {
133 | case null:
134 | return context.Fail($"Json property {propertyName} in {objectDescription} is null.");
135 | case JsonValue value:
136 | context.Ensure(value.TryGetValue(out var result), $"Json property {propertyName} in {objectDescription} cannot be converted to a {typeof(T).Name}.");
137 | return result ?? context.Fail($"Json property {propertyName} in {objectDescription} has a null value.");
138 | default:
139 | return context.Fail($"Json property {propertyName} in {objectDescription} is a {property.GetType().Name}, not a {nameof(JsonValue)}.");
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/build/nbgv.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Nerdbank.GitVersioning helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System.Text;
11 | using System.Text.Json.Nodes;
12 |
13 | /*
14 | * Summary : Gets version information using the NBGV tool.
15 | * Params : context - The Cake context.
16 | * Returns : VersionStr - The project version.
17 | * Ref - The Git ref from which we are building.
18 | * IsPublicRelease - True if a public release can be built, false otherwise.
19 | * IsPrerelease - True if the project version is tagged as prerelease, false otherwise.
20 | */
21 | static (string VersionStr, string Ref, bool IsPublicRelease, bool IsPrerelease) GetVersionInformation(this ICakeContext context)
22 | {
23 | var nbgvOutput = new StringBuilder();
24 | context.DotNetTool(
25 | "nbgv get-version --format json",
26 | new DotNetToolSettings {
27 | SetupProcessSettings = s => s
28 | .SetRedirectStandardOutput(true)
29 | .SetRedirectedStandardOutputHandler(x => {
30 | nbgvOutput.AppendLine(x);
31 | return x;
32 | }),
33 | });
34 |
35 | var json = context.ParseJsonObject(nbgvOutput.ToString(), "The output of nbgv");
36 | return (
37 | VersionStr: context.GetJsonPropertyValue(json, "SemVer2", "the output of nbgv"),
38 | Ref: context.GetJsonPropertyValue(json, "BuildingRef", "the output of nbgv"),
39 | IsPublicRelease: context.GetJsonPropertyValue(json, "PublicRelease", "the output of nbgv"),
40 | IsPrerelease: !string.IsNullOrEmpty(context.GetJsonPropertyValue(json, "PrereleaseVersion", "the output of nbgv")));
41 | }
42 |
--------------------------------------------------------------------------------
/build/options.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Option helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System.ComponentModel;
11 | using System.Linq;
12 |
13 | /*
14 | * Summary : Tells whether the specified option is present, either as an argument
15 | * or as an environment variable.
16 | * Params : context - The Cake context.
17 | * name - The option name.
18 | * environmentPrefix - An optional prefix for the environment variable name;
19 | * for example, camelCasedOption (prefix = "MYAPP_") -> MYAPP_CAMEL_CASED_OPTION
20 | * Returns : If an argument with the specified name is present, true;
21 | * if an environment variable with the specified name (converted according to environmentPrefix)
22 | * is present, true; otherwise, false.
23 | */
24 | static bool HasOption(this ICakeContext context, string name, string? environmentPrefix = null)
25 | => context.HasArgument(name) || context.HasEnvironmentVariable(OptionNameToEnvironmentVariableName(name, environmentPrefix));
26 |
27 | /*
28 | * Summary : Gets an option from, in this order:
29 | * * a command line argument with the specified name;
30 | * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE;
31 | * * the provided default value.
32 | * Params : context - The Cake context.
33 | * name - The option name.
34 | * defaultValue - The value returned if neither a corresponding argument
35 | * nor environment variable was found.
36 | */
37 | static T GetOption(this ICakeContext context, string name, T defaultValue)
38 | where T : notnull
39 | => context.GetOption(name, null, defaultValue);
40 |
41 | /*
42 | * Summary : Gets an option from, in this order:
43 | * * a command line argument with the specified name;
44 | * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE
45 | * and optionally prefixed with the specified environmentPrefix;
46 | * * the provided default value.
47 | * Params : context - The Cake context.
48 | * name - The option name.
49 | * environmentPrefix - An optional prefix for the environment variable name;
50 | * for example, "camelCasedOption" with an environmentPrefix
51 | * of "MYAPP_" becomes "MYAPP_CAMEL_CASED_OPTION".
52 | * defaultValue - The value returned if neither a corresponding argument
53 | * nor environment variable was found.
54 | */
55 | static T GetOption(this ICakeContext context, string name, string? environmentPrefix, T defaultValue)
56 | where T : notnull
57 | {
58 | var value = context.Arguments.GetArguments(name)?.FirstOrDefault();
59 | if (value != null)
60 | {
61 | return ConvertOption(value);
62 | }
63 |
64 | value = context.Environment.GetEnvironmentVariable(OptionNameToEnvironmentVariableName(name, environmentPrefix));
65 | return value == null ? defaultValue : ConvertOption(value);
66 | }
67 |
68 | /*
69 | * Summary : Gets an option from, in this order:
70 | * * a command line argument with the specified name;
71 | * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE;
72 | * * the provided default value.
73 | * Throw an exception if the option is not found or has an empty value.
74 | * Params : context - The Cake context.
75 | * name - The option name.
76 | */
77 | static T GetOptionOrFail(this ICakeContext context, string name)
78 | where T : notnull
79 | => context.GetOptionOrFail(name, null);
80 |
81 | /*
82 | * Summary : Gets an option from, in this order:
83 | * * a command line argument with the specified name;
84 | * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE
85 | * and optionally prefixed with the specified environmentPrefix;
86 | * * the provided default value.
87 | * Throw an exception if the option is not found or has an empty value.
88 | * Params : context - The Cake context.
89 | * name - The option name.
90 | * environmentPrefix - An optional prefix for the environment variable name;
91 | * for example, "camelCasedOption" with an environmentPrefix
92 | * of "MYAPP_" becomes "MYAPP_CAMEL_CASED_OPTION".
93 | */
94 | static T GetOptionOrFail(this ICakeContext context, string name, string? environmentPrefix)
95 | where T : notnull
96 | {
97 | var value = context.Arguments.GetArguments(name)?.FirstOrDefault();
98 | if (value != null)
99 | {
100 | return ConvertOption(value);
101 | }
102 |
103 | var envName = OptionNameToEnvironmentVariableName(name, environmentPrefix);
104 | value = context.Environment.GetEnvironmentVariable(envName);
105 | if (value != null)
106 | {
107 | return ConvertOption(value);
108 | }
109 |
110 | throw new CakeException($"Option {name} / environment variable {envName} not found or empty.");
111 | }
112 |
113 | /*
114 | * Summary : Converts an option name (which is supposed to be in camelCase)
115 | * to an environment variable name (UNDERSCORE_UPPER_CASE).
116 | * Params : prefix - An optional prefix for the environment variable name;
117 | * for example, camelCasedOption (prefix = "MYAPP_") -> MYAPP_CAMEL_CASED_OPTION
118 | */
119 | // Copyright (c) .NET Foundation and Contributors - MIT License - https://github.com/Humanizr/Humanizer
120 | static string OptionNameToEnvironmentVariableName(string name, string? prefix = null)
121 | => (prefix ?? string.Empty) + Regex.Replace(
122 | Regex.Replace(
123 | Regex.Replace(
124 | name,
125 | @"([\p{Lu}]+)([\p{Lu}][\p{Ll}])",
126 | "$1_$2"),
127 | @"([\p{Ll}\d])([\p{Lu}])",
128 | "$1_$2"),
129 | @"[-\s]",
130 | "_")
131 | .ToUpperInvariant();
132 |
133 | /*
134 | * Summary : Convert an option to the desired type.
135 | * Types : T - The type to convert the option to.
136 | * Params : value - The value of the option.
137 | * Returns : The converted value.
138 | */
139 | static T ConvertOption(string value)
140 | where T : notnull
141 | {
142 | var converter = TypeDescriptor.GetConverter(typeof(T));
143 | return (T)converter.ConvertFromInvariantString(value)!;
144 | }
145 |
--------------------------------------------------------------------------------
/build/process.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Process helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System.Collections.Generic;
11 |
12 | /*
13 | * Summary : Executes an external command, capturing standard output and failing if the exit code is not zero.
14 | * Params : context - The Cake context.
15 | * command - The name of the command to execute.
16 | * arguments - The arguments to pass to the command.
17 | * Returns : The captured output of the command.
18 | */
19 | static IEnumerable Exec(this ICakeContext context, string command, ProcessArgumentBuilder arguments)
20 | {
21 | var exitCode = context.Exec(command, arguments, out var output);
22 | context.Ensure(exitCode == 0, $"'{command} {arguments.RenderSafe()}' exited with code {exitCode}.");
23 | return output;
24 | }
25 |
26 | /*
27 | * Summary : Executes an external command, capturing standard output and failing if the exit code is not zero.
28 | * Params : context - The Cake context.
29 | * command - The name of the command to execute.
30 | * arguments - The arguments to pass to the command.
31 | * out output - The captured output of the command.
32 | * Returns : The exit code of the command.
33 | */
34 | static int Exec(this ICakeContext context, string command, ProcessArgumentBuilder arguments, out IEnumerable output)
35 | => context.StartProcess(
36 | command,
37 | new ProcessSettings { Arguments = arguments, RedirectStandardOutput = true },
38 | out output);
39 |
--------------------------------------------------------------------------------
/build/public-api.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Public API helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using System.Text;
13 |
14 | using SysFile = System.IO.File;
15 |
16 | /*
17 | * Summary : Specifies the kind of changes public APIs have undergone between an older and a newer version.
18 | * Remarks : The values of this enum are sorted in ascending order of importance,
19 | * so that they may be compared.
20 | */
21 | enum ApiChangeKind
22 | {
23 | /*
24 | * Summary : Public APIs have not changed between two versions.
25 | */
26 | None,
27 |
28 | /*
29 | * Summary : A newer version has only added public APIs with respect to an older version.
30 | */
31 | Additive,
32 |
33 | /*
34 | * Summary : A newer version's public APIs have undergone breaking changes since an older version was published.
35 | */
36 | Breaking,
37 | }
38 |
39 | /*
40 | * Summary : Gets the kind of change public APIs underwent, according to the presence of new public APIs
41 | * and/or the removal of existing public APIs in all PublicAPI.Unshipped.txt files
42 | * of the repository.
43 | * Params : context - The Cake context.
44 | * Returns : If at least one public API was removed, ApiChangeKind.Breaking;
45 | * if no public API was removed, but at least one was added, ApiChangeKind.Additive;
46 | * if no public API was removed nor added, ApiChangeKind.None.
47 | */
48 | static ApiChangeKind GetPublicApiChangeKind(this ICakeContext context)
49 | {
50 | context.Information("Computing API change kind according to unshipped public API files...");
51 | var result = ApiChangeKind.None;
52 | foreach (var unshippedPath in context.GetAllPublicApiFilePairs().Select(pair => pair.UnshippedPath))
53 | {
54 | var fileResult = context.GetPublicApiChangeKind(unshippedPath);
55 | context.Verbose($"{unshippedPath} -> {fileResult}");
56 | if (fileResult == ApiChangeKind.Breaking)
57 | {
58 | return ApiChangeKind.Breaking;
59 | }
60 | else if (fileResult > result)
61 | {
62 | result = fileResult;
63 | }
64 | }
65 |
66 | return result;
67 | }
68 |
69 | /*
70 | * Summary : Transfers unshipped public API definitions to PublicAPI.Shipped.txt
71 | * in all directories of the repository.
72 | * Params : context - The Cake context.
73 | * Returns : An enumeration of the modified files.
74 | */
75 | static IEnumerable TransferAllPublicApiToShipped(this ICakeContext context)
76 | {
77 | context.Information("Updating public API files...");
78 | foreach (var pair in context.GetAllPublicApiFilePairs())
79 | {
80 | context.Verbose($"Updating {pair.ShippedPath}...");
81 | if (context.TransferPublicApiToShipped(pair.UnshippedPath, pair.ShippedPath))
82 | {
83 | yield return pair.ShippedPath;
84 | yield return pair.UnshippedPath;
85 | }
86 | }
87 | }
88 |
89 | /*
90 | * Summary : Gets all public API definition file pairs in the repository.
91 | * Params : context - The Cake context.
92 | * Returns : An enumeration of (UnshippedPath, ShippedPath) tuples.
93 | */
94 | static IEnumerable<(FilePath UnshippedPath, FilePath ShippedPath)> GetAllPublicApiFilePairs(this ICakeContext context)
95 | {
96 | (FilePath UnshippedPath, FilePath ShippedPath)? GetPair(FilePath shippedPath)
97 | {
98 | var unshippedPath = shippedPath.GetDirectory().CombineWithFilePath("PublicAPI.Unshipped.txt");
99 | return context.FileSystem.Exist(unshippedPath) ? (unshippedPath, shippedPath) : null;
100 | }
101 |
102 | return context
103 | .GetFiles("**/PublicAPI.Shipped.txt", new() { IsCaseSensitive = true })
104 | .Select(GetPair)
105 | .Where(maybePair => maybePair.HasValue)
106 | .Select(maybePair => maybePair!.Value);
107 | }
108 |
109 | /*
110 | * Summary : Gets the kind of change public APIs underwent, according to the presence of new public APIs
111 | * and/or the removal of existing public APIs.
112 | * Params : context - The Cake context.
113 | * unshippedPath - The FilePath of PublicAPI.Unshipped.txt
114 | * Returns : If at least one public API was removed, ApiChangeKind.Breaking;
115 | * if no public API was removed, but at least one was added, ApiChangeKind.Additive;
116 | * if no public API was removed nor added, ApiChangeKind.None.
117 | */
118 | static ApiChangeKind GetPublicApiChangeKind(this ICakeContext context, FilePath unshippedPath)
119 | {
120 | var unshippedLines = SysFile.ReadAllLines(unshippedPath.FullPath, Encoding.UTF8);
121 | static bool IsEmptyOrStartsWithHash(string s) => s.Length == 0 || s[0] == '#';
122 | var unshippedPublicApiLines = unshippedLines.SkipWhile(IsEmptyOrStartsWithHash);
123 | const string RemovedPrefix = "*REMOVED*";
124 | var newApiPresent = false;
125 | foreach (var line in unshippedPublicApiLines)
126 | {
127 | if (line.StartsWith(RemovedPrefix, StringComparison.Ordinal))
128 | {
129 | return ApiChangeKind.Breaking;
130 | }
131 |
132 | newApiPresent = true;
133 | }
134 |
135 | return newApiPresent ? ApiChangeKind.Additive : ApiChangeKind.None;
136 | }
137 |
138 | /*
139 | * Summary : Transfers unshipped public API definitions to PublicAPI.Shipped.txt
140 | * Params : context - The Cake context.
141 | * unshippedPath - The FilePath of PublicAPI.Unshipped.txt
142 | * shippedPath - The FilePath of PublicAPI.Shipped.txt
143 | * Returns : true if files were modified; false otherwise.
144 | */
145 | static bool TransferPublicApiToShipped(this ICakeContext context, FilePath unshippedPath, FilePath shippedPath)
146 | {
147 | var utf8 = new UTF8Encoding(false);
148 | var unshippedLines = SysFile.ReadAllLines(unshippedPath.FullPath, utf8);
149 | var unshippedHeaderLines = unshippedLines.TakeWhile(IsEmptyOrStartsWithHash).ToArray();
150 | if (unshippedHeaderLines.Length == unshippedLines.Length)
151 | {
152 | return false;
153 | }
154 |
155 | static bool IsEmptyOrStartsWithHash(string s) => s.Length == 0 || s[0] == '#';
156 | var shippedLines = SysFile.ReadAllLines(shippedPath.FullPath, utf8);
157 | var shippedHeaderLines = shippedLines.TakeWhile(IsEmptyOrStartsWithHash).ToArray();
158 |
159 | const string RemovedPrefix = "*REMOVED*";
160 | static bool StartsWithRemovedPrefix(string s) => s.StartsWith(RemovedPrefix, StringComparison.Ordinal);
161 | static bool DoesNotStartWithRemovedPrefix(string s) => !StartsWithRemovedPrefix(s);
162 | var removedLines = unshippedLines
163 | .Skip(unshippedHeaderLines.Length)
164 | .Where(StartsWithRemovedPrefix)
165 | .Select(l => l[(RemovedPrefix.Length)..])
166 | .OrderBy(l => l, StringComparer.Ordinal) // For BinarySearch
167 | .ToArray();
168 |
169 | bool IsNotRemoved(string s) => Array.BinarySearch(removedLines, s, StringComparer.Ordinal) < 0;
170 | var newShippedLines = shippedLines
171 | .Skip(shippedHeaderLines.Length)
172 | .Where(IsNotRemoved)
173 | .Concat(unshippedLines
174 | .Skip(unshippedHeaderLines.Length)
175 | .Where(DoesNotStartWithRemovedPrefix))
176 | .OrderBy(l => l, StringComparer.Ordinal);
177 |
178 | SysFile.WriteAllLines(shippedPath.FullPath, shippedHeaderLines.Concat(newShippedLines), utf8);
179 | SysFile.WriteAllLines(unshippedPath.FullPath, unshippedHeaderLines, utf8);
180 | return true;
181 | }
182 |
--------------------------------------------------------------------------------
/build/setup-teardown.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // =============================================================================================
7 | // Setup and Teardown, common to all scripts
8 | // =============================================================================================
9 |
10 | Setup(context =>
11 | {
12 | var data = new BuildData(context);
13 | if (data.IsCI && !data.IsGitHubAction)
14 | {
15 | throw new CakeException(255, "This script can only run locally or in a GitHub Actions workflow.");
16 | }
17 |
18 | return data;
19 | });
20 |
21 | Teardown((context, data) =>
22 | {
23 | // For some reason, DotNetBuildServerShutdown hangs in a GitHub Actions runner;
24 | // it is still useful on a local machine though
25 | if (!data.IsCI)
26 | {
27 | context.DotNetBuildServerShutdown(new DotNetBuildServerShutdownSettings
28 | {
29 | Razor = true,
30 | VBCSCompiler = true,
31 | });
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/build/utilities.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Miscellaneous utilities
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | using System;
11 | using System.Linq;
12 |
13 | /*
14 | * Summary : Filters a sequence of nullable values, taking only those that are not null.
15 | * Type params : T - The type of the elements of this.
16 | * Params : this - An IEnumerable to filter.
17 | * Returns : An IEnumerable that contains elements from the input sequence that are not null.
18 | */
19 | static IEnumerable WhereNotNull(this IEnumerable @this)
20 | where T : class
21 | {
22 | return @this.Where(IsNotNull) as IEnumerable;
23 |
24 | static bool IsNotNull(T? x) => x is not null;
25 | }
26 |
27 | /*
28 | * Summary : Filters a sequence of nullable values, taking only those that are not null.
29 | * Type params : T - The type of the elements of this.
30 | * Params : this - An IEnumerable to filter.
31 | * Returns : An IEnumerable that contains elements from the input sequence that are not null.
32 | */
33 | public static IEnumerable WhereNotNull(this IEnumerable @this)
34 | where T : struct
35 | {
36 | return @this.Where(IsNotNull).Select(GetValue);
37 |
38 | static bool IsNotNull(T? x) => x.HasValue;
39 |
40 | static T GetValue(T? x) => x!.Value;
41 | }
42 |
--------------------------------------------------------------------------------
/build/workspace.cake:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See LICENSE file in the project root for full license information.
3 |
4 | #nullable enable
5 |
6 | // ---------------------------------------------------------------------------------------------
7 | // Workspace helpers
8 | // ---------------------------------------------------------------------------------------------
9 |
10 | /*
11 | * Summary : Delete all intermediate and output directories.
12 | * On a local machine, also delete Visual Studio and ReSharper caches.
13 | * Params : context - The Cake context.
14 | */
15 | static void CleanAll(this ICakeContext context, BuildData data)
16 | {
17 | context.DeleteDirectoryIfExists(".vs");
18 | context.DeleteDirectoryIfExists("_ReSharper.Caches");
19 | context.DeleteDirectoryIfExists("artifacts");
20 | context.DeleteDirectoryIfExists("logs");
21 | context.DeleteDirectoryIfExists("TestResults");
22 | foreach (var project in data.Solution.Projects)
23 | {
24 | var projectDirectory = project.Path.GetDirectory();
25 | context.DeleteDirectoryIfExists(projectDirectory.Combine("bin"));
26 | context.DeleteDirectoryIfExists(projectDirectory.Combine("obj"));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "8.0.100",
4 | "rollForward": "latestMinor",
5 | "allowPrerelease": false
6 | },
7 | "msbuild-sdks": {
8 | "Buildvana.Sdk": "1.0.122-preview",
9 | "Microsoft.Build.NoTargets": "3.7.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/graphics/PackageIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tenacom/PolyKit/97de16ce19a0b67791000839106715bee6393400/graphics/PackageIcon.png
--------------------------------------------------------------------------------
/graphics/README.md:
--------------------------------------------------------------------------------
1 | # Graphics
2 |
3 | All the graphic elements listed below, except where otherwise specified, are Copyright (C) Tenacom and Contributors and are licensed under the MIT license. See the LICENSE file in the project root for full license information.
4 |
5 | ## `SquareLogo`
6 |
7 | Reference logo, basic square logo. Used as NuGet package icon, favicon for web-based documentation, and anywhere a square-shaped logo is needed or preferred.
8 |
9 | This is a modifed version of [Putty Knife](https://thenounproject.com/icon/3765029) by Ranah Pixel Studio. The original file was obtained from [the Noun Project](https://thenounproject.com/) under the [Creative Commons Attribution 3.0 Unported (CC BY 3.0)](https://creativecommons.org/licenses/by/3.0/) license.
10 |
11 | Modified by [@rdeago](https://github.com/rdeago).
12 |
13 | Related files:
14 |
15 | - `PackageIcon.png` (512x512px)
16 | 
17 |
18 | - `docs/logo.svg` (optimized)
19 | 
20 |
21 | - `docs/favicon.ico` (16x16px,32bpp; 32x32px,32bpp; 48x48px,32bpp; 64x64px,32bpp; 128x128px,32bpp)
22 | 
23 |
24 | ## `Readme`
25 |
26 | Graphic header for README file.
27 |
28 | Uses the following material: [SquareLogo](#squarelogo); [Repo](#repo).
29 |
30 | Related files:
31 |
32 | - `Readme.png` (540x160px)
33 | 
34 |
35 | ## `SocialCard`
36 |
37 | Social card for GitHub project.
38 |
39 | Uses the following material: [SquareLogo](#squarelogo); [Repo](#repo); [Courier Prime](#courier-prime).
40 |
41 | Related files:
42 |
43 | - `SocialCard.png` (1280x640px)
44 | 
45 |
46 | ## Third-party material
47 |
48 | The following third-party material was used to produce the above files.
49 |
50 | ### Repo
51 |
52 | The [Repo](https://fontlibrary.org/en/font/repo) font, by Stefan Peev, was obtained from [Font Library](https://fontlibrary.org) under the [SIL Open Font License (OFL)](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL).
53 |
54 | ### Courier Prime
55 |
56 | The [Courier Prime](https://fontlibrary.org/en/font/courier-prime) font, by Alan Dague-Greene of Quote-Unquote Apps, was obtained from [Font Library](https://fontlibrary.org) under the [SIL Open Font License (OFL)](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL).
57 |
--------------------------------------------------------------------------------
/graphics/Readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tenacom/PolyKit/97de16ce19a0b67791000839106715bee6393400/graphics/Readme.png
--------------------------------------------------------------------------------
/graphics/SocialCard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tenacom/PolyKit/97de16ce19a0b67791000839106715bee6393400/graphics/SocialCard.png
--------------------------------------------------------------------------------
/graphics/SquareLogo.svg:
--------------------------------------------------------------------------------
1 |
2 |
130 |
--------------------------------------------------------------------------------
/graphics/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tenacom/PolyKit/97de16ce19a0b67791000839106715bee6393400/graphics/docs/favicon.ico
--------------------------------------------------------------------------------
/graphics/docs/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/PolyKit.Embedded/PolyKit.Embedded.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Embeds polyfills in your project, creating either internal or public types.
5 | net8.0
6 | true
7 |
8 | true
9 |
10 |
11 |
15 |
16 | true
17 | $(BaseIntermediateOutputPath)\Generated
18 | false
19 |
20 |
21 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/PolyKit.Generator/PolyKit.Generator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | true
6 | true
7 | false
8 |
9 | false
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/PolyKit.Generator/PolyfillGenerator.cs:
--------------------------------------------------------------------------------
1 | // Copyright (C) Tenacom and contributors. Licensed under the MIT license.
2 | // See the LICENSE file in the project root for full license information.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Reflection;
9 | using System.Text;
10 | using System.Text.RegularExpressions;
11 | using Microsoft.CodeAnalysis;
12 |
13 | #pragma warning disable CA1050 // Declare types in namespaces
14 |
15 | ///
16 | /// Adds polyfill source files to a project.
17 | ///
18 | [Generator(LanguageNames.CSharp)]
19 | public class PolyfillGenerator : IIncrementalGenerator
20 | {
21 | private const string Eol = "\r\n";
22 |
23 | // All polyfill source files are saved as UTF-8 with BOM, with lines separated by CR+LF.
24 | // (see .editorconfig in the project root)
25 | private static readonly IReadOnlyCollection Header = new[]
26 | {
27 | "// ",
28 | "// >>>> DO NOT MODIFY THIS FILE <<<<",
29 | "//",
30 | "// This file is part of the PolyKit.Embedded NuGet package and resides in your local NuGet cache.",
31 | "// Any modification you make will influence all projects on your machine that reference PolyKit.Embedded.",
32 | "// Modifications will be undone anyway as soon as you update PolyKit.Embedded or clear your local NuGet cache.",
33 | "//",
34 | "// If there seems to be a problem with this file:",
35 | "// - First of all, be sure to read the documentation at https://github.com/Tenacom/PolyKit#readme",
36 | "// - If you have a doubt or want to ask a question, you are welcome to our Discussions area",
37 | "// at https://github.com/Tenacom/PolyKit/discussions",
38 | "// - Please check whether there is already an issue that applies to your problem",
39 | "// at https://github.com/Tenacom/PolyKit/issues - you may find an existing solution or workaround",
40 | "// - If you think you have found a bug that has not been reported yet,",
41 | "// or have an idea that may help improve the PolyKit project,",
42 | "// you are welcome to open a new issue at https://github.com/Tenacom/PolyKit/issues/new",
43 | "//",
44 | "// This file is part of PolyKit.Embedded version " + ThisAssembly.AssemblyInformationalVersion,
45 | "// and is provided under one or more license agreements.",
46 | "// Please see https://github.com/Tenacom/PolyKit for full license information.",
47 | "// ",
48 | string.Empty,
49 | "#nullable enable",
50 | string.Empty,
51 | "#pragma warning disable RS0016 // Add public types and members to the declared API",
52 | "#pragma warning disable RS0041 // Public members should not use oblivious types",
53 | string.Empty,
54 | };
55 |
56 | private static readonly Regex PolyfillRegex = new(
57 | @"^(\s*)public(?:\s*)//(?:\s*)polyfill!((?:\+|-)?)(?:\s|$)",
58 | RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.Singleline);
59 |
60 | // For the rationale behind the added attributes, see this article:
61 | // https://riccar.do/posts/2022/2022-05-30-well-behaved-guest-code.html
62 | private static readonly IReadOnlyCollection AdditionalPolyfillLines = new[]
63 | {
64 | "[System.Diagnostics.DebuggerNonUserCode]",
65 | "[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]",
66 | };
67 | private static readonly IReadOnlyCollection PolyfillLines = new[]
68 | {
69 | "[System.CodeDom.Compiler.GeneratedCode(\"PolyKit.Embedded\", \"" + ThisAssembly.AssemblyInformationalVersion + "\")]",
70 | "#if POLYKIT_PUBLIC",
71 | "public",
72 | "#else",
73 | "internal",
74 | "#endif",
75 | };
76 |
77 | ///
78 | public void Initialize(IncrementalGeneratorInitializationContext context)
79 | => context.RegisterPostInitializationOutput(static ctx =>
80 | {
81 | var assembly = Assembly.GetExecutingAssembly();
82 | var names = assembly.GetManifestResourceNames()
83 | .Where(n => n.EndsWith(".cs", StringComparison.Ordinal))
84 | .Select(s => s.Substring(0, s.Length - 3));
85 |
86 | var sb = new StringBuilder(16 * 1024);
87 | foreach (var line in Header)
88 | {
89 | _ = sb.Append(line).Append(Eol);
90 | }
91 |
92 | var headerLength = sb.Length;
93 | foreach (var name in names)
94 | {
95 | using (var inStream = assembly.GetManifestResourceStream(name + ".cs"))
96 | using (var reader = new StreamReader(inStream, Encoding.UTF8))
97 | {
98 | for (; ;)
99 | {
100 | var line = reader.ReadLine();
101 | if (line == null)
102 | {
103 | break;
104 | }
105 |
106 | var match = PolyfillRegex.Match(line);
107 | if (!match.Success)
108 | {
109 | _ = sb.Append(line).Append(Eol);
110 | continue;
111 | }
112 |
113 | var indentation = match.Groups[1].Captures[0].Value;
114 | var modifier = match.Groups[2].Captures[0].Value;
115 |
116 | // Additional polyfill lines contain attributes that are not valid on enums and interfaces
117 | var replacementLines = modifier == "-"
118 | ? PolyfillLines
119 | : AdditionalPolyfillLines.Concat(PolyfillLines);
120 |
121 | foreach (var replacementLine in replacementLines)
122 | {
123 | // Only indent non-empty lines; never indent preprocessor directives
124 | if (replacementLine.Length > 0 && replacementLine[0] != '#')
125 | {
126 | _ = sb.Append(indentation);
127 | }
128 |
129 | _ = sb.Append(replacementLine).Append(Eol);
130 | }
131 | }
132 | }
133 |
134 | ctx.AddSource(name + ".g.cs", sb.ToString());
135 | sb.Length = headerLength;
136 | }
137 | });
138 | }
139 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/PolyKit.Polyfills.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 | netstandard2.0;netstandard2.1;net462;net47;net6.0;net7.0;net8.0
14 | 12
15 |
16 | false
17 |
18 |
19 |
20 |
21 | None
22 | false
23 |
24 |
25 |
26 |
27 | $(NoWarn);CA1812
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/PolyKit/Diagnostics/CodeAnalysis/ValidatedNotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace PolyKit.Diagnostics.CodeAnalysis;
4 |
5 | ///
6 | /// Indicates to Code Analysis that a method validates a parameter,
7 | /// so that if / when the method returns the parameter is known to be non-null.
8 | ///
9 | [AttributeUsage(AttributeTargets.Parameter)]
10 | public // polyfill!
11 | sealed class ValidatedNotNullAttribute : Attribute
12 | {
13 | }
14 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/AllowNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.AllowNullAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L7
14 |
15 | ///
16 | /// Specifies that null is allowed as an input even if the corresponding type disallows it.
17 | ///
18 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
19 | public // polyfill!
20 | sealed class AllowNullAttribute : Attribute
21 | {
22 | }
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/ConstantExpectedAttribute.cs:
--------------------------------------------------------------------------------
1 | #if POLYKIT_NETSDK7_0_OR_GREATER
2 | #if NET7_0_OR_GREATER
3 |
4 | #if POLYKIT_PUBLIC
5 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.ConstantExpectedAttribute))]
6 | #endif
7 |
8 | #else
9 |
10 | // Licensed to the .NET Foundation under one or more agreements.
11 | // The .NET Foundation licenses this file to you under the MIT license.
12 | namespace System.Diagnostics.CodeAnalysis;
13 |
14 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ConstantExpectedAttribute.cs
15 |
16 | ///
17 | /// Indicates that the specified method parameter expects a constant.
18 | ///
19 | ///
20 | /// This can be used to inform tooling that a constant should be used as an argument for the annotated parameter.
21 | ///
22 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
23 | public // polyfill!
24 | sealed class ConstantExpectedAttribute : Attribute
25 | {
26 | ///
27 | /// Gets or sets the minimum bound of the expected constant, inclusive.
28 | ///
29 | public object? Min { get; set; }
30 |
31 | ///
32 | /// Gets or sets the maximum bound of the expected constant, inclusive.
33 | ///
34 | public object? Max { get; set; }
35 | }
36 |
37 | #endif
38 | #endif
39 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/DisallowNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DisallowNullAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L16
14 |
15 | ///
16 | /// Specifies that null is disallowed as an input even if the corresponding type allows it.
17 | ///
18 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
19 | public // polyfill!
20 | sealed class DisallowNullAttribute : Attribute
21 | {
22 | }
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/DoesNotReturnAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L100
14 |
15 | ///
16 | /// Applied to a method that will never return under any circumstance.
17 | ///
18 | [AttributeUsage(AttributeTargets.Method, Inherited = false)]
19 | public // polyfill!
20 | sealed class DoesNotReturnAttribute : Attribute
21 | {
22 | }
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/DoesNotReturnIfAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L109
14 |
15 | ///
16 | /// Applied to a method that will never return under any circumstance.
17 | ///
18 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
19 | public // polyfill!
20 | sealed class DoesNotReturnIfAttribute : Attribute
21 | {
22 | ///
23 | /// Initializes a new instance of the class
24 | /// with the specified parameter value.
25 | ///
26 | ///
27 | /// The condition parameter value.
28 | /// Code after the method will be considered unreachable by diagnostics
29 | /// if the argument to the associated parameter matches this value.
30 | ///
31 | public DoesNotReturnIfAttribute(bool parameterValue)
32 | {
33 | ParameterValue = parameterValue;
34 | }
35 |
36 | #pragma warning disable SA1623 // Property summary documentation should match accessors - "Gets a value indicating whether..." is not suitable here.
37 | ///
38 | /// Gets the condition parameter value.
39 | ///
40 | public bool ParameterValue { get; }
41 | #pragma warning restore SA1623 // Property summary documentation should match accessors
42 | }
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/DynamicDependencyAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicDependencyAttribute.cs
14 |
15 | ///
16 | /// States a dependency that one member has on another.
17 | ///
18 | ///
19 | /// This can be used to inform tooling of a dependency that is otherwise not evident purely from
20 | /// metadata and IL, for example a member relied on via reflection.
21 | ///
22 | [AttributeUsage(
23 | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method,
24 | AllowMultiple = true,
25 | Inherited = false)]
26 | public // polyfill!
27 | sealed class DynamicDependencyAttribute : Attribute
28 | {
29 | ///
30 | /// Initializes a new instance of the class
31 | /// with the specified signature of a member on the same type as the consumer.
32 | ///
33 | /// The signature of the member depended on.
34 | public DynamicDependencyAttribute(string memberSignature)
35 | {
36 | MemberSignature = memberSignature;
37 | }
38 |
39 | ///
40 | /// Initializes a new instance of the class
41 | /// with the specified signature of a member on a .
42 | ///
43 | /// The signature of the member depended on.
44 | /// The containing .
45 | public DynamicDependencyAttribute(string memberSignature, Type type)
46 | {
47 | MemberSignature = memberSignature;
48 | Type = type;
49 | }
50 |
51 | ///
52 | /// Initializes a new instance of the class
53 | /// with the specified signature of a member on a type in an assembly.
54 | ///
55 | /// The signature of the member depended on.
56 | /// The full name of the type containing the specified member.
57 | /// The assembly name of the type containing the specified member.
58 | public DynamicDependencyAttribute(string memberSignature, string typeName, string assemblyName)
59 | {
60 | MemberSignature = memberSignature;
61 | TypeName = typeName;
62 | AssemblyName = assemblyName;
63 | }
64 |
65 | ///
66 | /// Initializes a new instance of the class
67 | /// with the specified types of members on a .
68 | ///
69 | /// The types of members depended on.
70 | /// The containing the specified members.
71 | public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, Type type)
72 | {
73 | MemberTypes = memberTypes;
74 | Type = type;
75 | }
76 |
77 | ///
78 | /// Initializes a new instance of the class
79 | /// with the specified types of members on a type in an assembly.
80 | ///
81 | /// The types of members depended on.
82 | /// The full name of the type containing the specified members.
83 | /// The assembly name of the type containing the specified members.
84 | public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, string typeName, string assemblyName)
85 | {
86 | MemberTypes = memberTypes;
87 | TypeName = typeName;
88 | AssemblyName = assemblyName;
89 | }
90 |
91 | ///
92 | /// Gets the signature of the member depended on.
93 | ///
94 | ///
95 | /// Either must be a valid string or
96 | /// must not equal , but not both.
97 | ///
98 | public string? MemberSignature { get; }
99 |
100 | ///
101 | /// Gets the which specifies the type
102 | /// of members depended on.
103 | ///
104 | ///
105 | /// Either must be a valid string or
106 | /// must not equal , but not both.
107 | ///
108 | public DynamicallyAccessedMemberTypes MemberTypes { get; }
109 |
110 | ///
111 | /// Gets the containing the specified member.
112 | ///
113 | ///
114 | /// If neither nor are specified,
115 | /// the type of the consumer is assumed.
116 | ///
117 | public Type? Type { get; }
118 |
119 | ///
120 | /// Gets the full name of the type containing the specified member.
121 | ///
122 | ///
123 | /// If neither nor are specified,
124 | /// the type of the consumer is assumed.
125 | ///
126 | public string? TypeName { get; }
127 |
128 | ///
129 | /// Gets the assembly name of the specified type.
130 | ///
131 | ///
132 | /// is only valid when is specified.
133 | ///
134 | public string? AssemblyName { get; }
135 |
136 | ///
137 | /// Gets or sets the condition in which the dependency is applicable, e.g. "DEBUG".
138 | ///
139 | public string? Condition { get; set; }
140 | }
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs
14 |
15 | ///
16 | /// Specifies the types of members that are dynamically accessed.
17 | ///
18 | /// This enumeration has a attribute that allows a
19 | /// bitwise combination of its member values.
20 | ///
21 | [Flags]
22 | public // polyfill!-
23 | enum DynamicallyAccessedMemberTypes
24 | {
25 | ///
26 | /// Specifies no members.
27 | ///
28 | None = 0,
29 |
30 | ///
31 | /// Specifies the default, parameterless public constructor.
32 | ///
33 | PublicParameterlessConstructor = 0x0001,
34 |
35 | ///
36 | /// Specifies all public constructors.
37 | ///
38 | PublicConstructors = 0x0002 | PublicParameterlessConstructor,
39 |
40 | ///
41 | /// Specifies all non-public constructors.
42 | ///
43 | NonPublicConstructors = 0x0004,
44 |
45 | ///
46 | /// Specifies all public methods.
47 | ///
48 | PublicMethods = 0x0008,
49 |
50 | ///
51 | /// Specifies all non-public methods.
52 | ///
53 | NonPublicMethods = 0x0010,
54 |
55 | ///
56 | /// Specifies all public fields.
57 | ///
58 | PublicFields = 0x0020,
59 |
60 | ///
61 | /// Specifies all non-public fields.
62 | ///
63 | NonPublicFields = 0x0040,
64 |
65 | ///
66 | /// Specifies all public nested types.
67 | ///
68 | PublicNestedTypes = 0x0080,
69 |
70 | ///
71 | /// Specifies all non-public nested types.
72 | ///
73 | NonPublicNestedTypes = 0x0100,
74 |
75 | ///
76 | /// Specifies all public properties.
77 | ///
78 | PublicProperties = 0x0200,
79 |
80 | ///
81 | /// Specifies all non-public properties.
82 | ///
83 | NonPublicProperties = 0x0400,
84 |
85 | ///
86 | /// Specifies all public events.
87 | ///
88 | PublicEvents = 0x0800,
89 |
90 | ///
91 | /// Specifies all non-public events.
92 | ///
93 | NonPublicEvents = 0x1000,
94 |
95 | ///
96 | /// Specifies all interfaces implemented by the type.
97 | ///
98 | Interfaces = 0x2000,
99 |
100 | ///
101 | /// Specifies all members.
102 | ///
103 | All = ~None,
104 | }
105 |
106 | #endif
107 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs
14 |
15 | ///
16 | /// Indicates that certain members on a specified are accessed dynamically,
17 | /// for example through .
18 | ///
19 | ///
20 | /// This allows tools to understand which members are being accessed during the execution
21 | /// of a program.
22 | /// This attribute is valid on members whose type is or .
23 | /// When this attribute is applied to a location of type , the assumption is
24 | /// that the string represents a fully qualified type name.
25 | /// When this attribute is applied to a class, interface, or struct, the members specified
26 | /// can be accessed dynamically on instances returned from calling
27 | /// on instances of that class, interface, or struct.
28 | /// If the attribute is applied to a method it's treated as a special case and it implies
29 | /// the attribute should be applied to the "this" parameter of the method. As such the attribute
30 | /// should only be used on instance methods of types assignable to System.Type (or string, but no methods
31 | /// will use it there).
32 | ///
33 | [AttributeUsage(
34 | AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter |
35 | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method |
36 | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct,
37 | Inherited = false)]
38 | public // polyfill!
39 | sealed class DynamicallyAccessedMembersAttribute : Attribute
40 | {
41 | ///
42 | /// Initializes a new instance of the class
43 | /// with the specified member types.
44 | ///
45 | /// The types of members dynamically accessed.
46 | public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
47 | {
48 | MemberTypes = memberTypes;
49 | }
50 |
51 | ///
52 | /// Gets the which specifies the type
53 | /// of members dynamically accessed.
54 | ///
55 | public DynamicallyAccessedMemberTypes MemberTypes { get; }
56 | }
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs:
--------------------------------------------------------------------------------
1 | #if POLYKIT_NETSDK8_0_OR_GREATER
2 | #if NET8_0_OR_GREATER
3 |
4 | #if POLYKIT_PUBLIC
5 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.ExperimentalAttribute))]
6 | #endif
7 |
8 | #else
9 |
10 | // Licensed to the .NET Foundation under one or more agreements.
11 | // The .NET Foundation licenses this file to you under the MIT license.
12 |
13 | namespace System.Diagnostics.CodeAnalysis;
14 |
15 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExperimentalAttribute.cs
16 |
17 | ///
18 | /// Indicates that an API is experimental and it may change in the future.
19 | ///
20 | ///
21 | /// This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental feature is used.
22 | /// Authors can use this attribute to ship preview features in their assemblies.
23 | ///
24 | [AttributeUsage(
25 | AttributeTargets.Assembly
26 | | AttributeTargets.Module
27 | | AttributeTargets.Class
28 | | AttributeTargets.Struct
29 | | AttributeTargets.Enum
30 | | AttributeTargets.Constructor
31 | | AttributeTargets.Method
32 | | AttributeTargets.Property
33 | | AttributeTargets.Field
34 | | AttributeTargets.Event
35 | | AttributeTargets.Interface
36 | | AttributeTargets.Delegate,
37 | Inherited = false)]
38 | public // polyfill!
39 | sealed class ExperimentalAttribute : Attribute
40 | {
41 | ///
42 | /// Initializes a new instance of the class, specifying the ID that the compiler will use
43 | /// when reporting a use of the API the attribute applies to.
44 | ///
45 | /// The ID that the compiler will use when reporting a use of the API the attribute applies to.
46 | public ExperimentalAttribute(string diagnosticId)
47 | {
48 | DiagnosticId = diagnosticId;
49 | }
50 |
51 | ///
52 | /// Gets the ID that the compiler will use when reporting a use of the API the attribute applies to.
53 | ///
54 | /// The unique diagnostic ID.
55 | ///
56 | /// The diagnostic ID is shown in build output for warnings and errors.
57 | /// This property represents the unique ID that can be used to suppress the warnings or errors, if needed.
58 | ///
59 | public string DiagnosticId { get; }
60 |
61 | ///
62 | /// Gets or sets the URL for corresponding documentation.
63 | /// The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID.
64 | ///
65 | /// The format string that represents a URL to corresponding documentation.
66 | ///
67 | /// An example format string is https://contoso.com/obsoletion-warnings/{0}.
68 | ///
69 | public string? UrlFormat { get; set; }
70 | }
71 |
72 | #endif
73 | #endif
74 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/MaybeNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MaybeNullAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L25
14 |
15 | ///
16 | /// Specifies that an output may be null even if the corresponding type disallows it.
17 | ///
18 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
19 | public // polyfill!
20 | sealed class MaybeNullAttribute : Attribute
21 | {
22 | }
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/MaybeNullWhenAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L43
14 |
15 | ///
16 | /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it.
17 | ///
18 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
19 | public // polyfill!
20 | sealed class MaybeNullWhenAttribute : Attribute
21 | {
22 | ///
23 | /// Initializes a new instance of the class
24 | /// with the specified return value condition.
25 | ///
26 | ///
27 | /// The return value condition. If the method returns this value, the associated parameter may be null.
28 | ///
29 | public MaybeNullWhenAttribute(bool returnValue)
30 | {
31 | ReturnValue = returnValue;
32 | }
33 |
34 | #pragma warning disable SA1623 // Property summary documentation should match accessors - "Gets a value indicating whether..." is not suitable here.
35 | ///
36 | /// Gets the return value condition.
37 | ///
38 | /// The return value condition.
39 | public bool ReturnValue { get; }
40 | #pragma warning restore SA1623 // Property summary documentation should match accessors
41 | }
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/MemberNotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MemberNotNullAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L130
14 |
15 | ///
16 | /// Specifies that the method or property will ensure that the listed field and property members have not-null values.
17 | ///
18 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
19 | public // polyfill!
20 | sealed class MemberNotNullAttribute : Attribute
21 | {
22 | ///
23 | /// Initializes a new instance of the class
24 | /// with a field or property member.
25 | ///
26 | ///
27 | /// The field or property member that is promised to be not-null.
28 | ///
29 | #pragma warning disable CA1019 // Define accessors for attribute arguments - The member parameter initializes the Members property so we're fine.
30 | public MemberNotNullAttribute(string member)
31 | #pragma warning restore CA1019 // Define accessors for attribute arguments
32 | {
33 | Members = new[] { member };
34 | }
35 |
36 | ///
37 | /// Initializes a new instance of the class
38 | /// with the list of field and property members.
39 | ///
40 | ///
41 | /// The list of field and property members that are promised to be not-null.
42 | ///
43 | public MemberNotNullAttribute(params string[] members)
44 | {
45 | Members = members;
46 | }
47 |
48 | ///
49 | /// Gets field or property member names.
50 | ///
51 | public string[] Members { get; }
52 | }
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/MemberNotNullWhenAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L155
14 |
15 | ///
16 | /// Specifies that the method or property will ensure that the listed field and property members
17 | /// have not-null values when returning with the specified return value condition.
18 | ///
19 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
20 | public // polyfill!
21 | sealed class MemberNotNullWhenAttribute : Attribute
22 | {
23 | ///
24 | /// Initializes a new instance of the class
25 | /// with the specified return value condition and a field or property member.
26 | ///
27 | ///
28 | /// The return value condition.
29 | /// If the method returns this value, the associated parameter will not be null.
30 | ///
31 | ///
32 | /// The field or property member that is promised to be not-null.
33 | ///
34 | #pragma warning disable CA1019 // Define accessors for attribute arguments - The member parameter initializes the Members property so we're fine.
35 | public MemberNotNullWhenAttribute(bool returnValue, string member)
36 | #pragma warning restore CA1019 // Define accessors for attribute arguments
37 | {
38 | ReturnValue = returnValue;
39 | Members = new[] { member };
40 | }
41 |
42 | ///
43 | /// Initializes a new instance of the class
44 | /// with the specified return value condition and list of field and property members.
45 | ///
46 | ///
47 | /// The return value condition.
48 | /// If the method returns this value, the associated parameter will not be null.
49 | ///
50 | ///
51 | /// The list of field and property members that are promised to be not-null.
52 | ///
53 | public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
54 | {
55 | ReturnValue = returnValue;
56 | Members = members;
57 | }
58 |
59 | #pragma warning disable SA1623 // Property summary documentation should match accessors - "Gets a value indicating whether..." is not suitable here.
60 | ///
61 | /// Gets the return value condition.
62 | ///
63 | public bool ReturnValue { get; }
64 | #pragma warning restore SA1623 // Property summary documentation should match accessors
65 |
66 | ///
67 | /// Gets field or property member names.
68 | ///
69 | public string[] Members { get; }
70 | }
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/NotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L34
14 |
15 | ///
16 | /// Specifies that an output will not be null even if the corresponding type allows it.
17 | /// Specifies that an input argument was not null when the call returns.
18 | ///
19 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
20 | public // polyfill!
21 | sealed class NotNullAttribute : Attribute
22 | {
23 | }
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/NotNullIfNotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L81
14 |
15 | ///
16 | /// Specifies that the output will be non-null if the named parameter is non-null.
17 | ///
18 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
19 | public // polyfill!
20 | sealed class NotNullIfNotNullAttribute : Attribute
21 | {
22 | ///
23 | /// Initializes a new instance of the class
24 | /// with the associated parameter name.
25 | ///
26 | ///
27 | /// The associated parameter name.
28 | /// The output will be non-null if the argument to the parameter specified is non-null.
29 | ///
30 | public NotNullIfNotNullAttribute(string parameterName)
31 | {
32 | ParameterName = parameterName;
33 | }
34 |
35 | ///
36 | /// Gets the associated parameter name.
37 | ///
38 | public string ParameterName { get; }
39 | }
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/NotNullWhenAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.NotNullWhenAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L62
14 |
15 | ///
16 | /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it.
17 | ///
18 | [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
19 | public // polyfill!
20 | sealed class NotNullWhenAttribute : Attribute
21 | {
22 | ///
23 | /// Initializes a new instance of the class
24 | /// with the specified return value condition.
25 | ///
26 | ///
27 | /// The return value condition. If the method returns this value, the associated parameter may be null.
28 | ///
29 | public NotNullWhenAttribute(bool returnValue)
30 | {
31 | ReturnValue = returnValue;
32 | }
33 |
34 | #pragma warning disable SA1623 // Property summary documentation should match accessors - "Gets a value indicating whether..." is not suitable here.
35 | ///
36 | /// Gets the return value condition.
37 | ///
38 | /// The return value condition.
39 | public bool ReturnValue { get; }
40 | #pragma warning restore SA1623 // Property summary documentation should match accessors
41 | }
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/RequiresAssemblyFilesAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NET6_0_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresAssemblyFilesAttribute.cs
14 |
15 | ///
16 | /// Indicates that the specified member requires assembly files to be on disk.
17 | ///
18 | [AttributeUsage(
19 | AttributeTargets.Constructor |
20 | AttributeTargets.Event |
21 | AttributeTargets.Method |
22 | AttributeTargets.Property,
23 | Inherited = false,
24 | AllowMultiple = false)]
25 | public // polyfill!
26 | sealed class RequiresAssemblyFilesAttribute : Attribute
27 | {
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | public RequiresAssemblyFilesAttribute()
32 | {
33 | }
34 |
35 | ///
36 | /// Initializes a new instance of the class.
37 | ///
38 | ///
39 | /// A message that contains information about the need for assembly files to be on disk.
40 | ///
41 | public RequiresAssemblyFilesAttribute(string message)
42 | {
43 | Message = message;
44 | }
45 |
46 | ///
47 | /// Gets an optional message that contains information about the need for
48 | /// assembly files to be on disk.
49 | ///
50 | public string? Message { get; }
51 |
52 | ///
53 | /// Gets or sets an optional URL that contains more information about the member,
54 | /// why it requires assembly files to be on disk, and what options a consumer has
55 | /// to deal with it.
56 | ///
57 | public string? Url { get; set; }
58 | }
59 |
60 | #endif
61 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs:
--------------------------------------------------------------------------------
1 | #if POLYKIT_NETSDK7_0_OR_GREATER
2 | #if NET7_0_OR_GREATER
3 |
4 | #if POLYKIT_PUBLIC
5 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute))]
6 | #endif
7 |
8 | #else
9 |
10 | // Licensed to the .NET Foundation under one or more agreements.
11 | // The .NET Foundation licenses this file to you under the MIT license.
12 | namespace System.Diagnostics.CodeAnalysis;
13 |
14 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs
15 |
16 | ///
17 | /// Indicates that the specified method requires the ability to generate new code at runtime,
18 | /// for example through .
19 | ///
20 | ///
21 | /// This allows tools to understand which methods are unsafe to call when compiling ahead of time.
22 | ///
23 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
24 | public // polyfill!
25 | sealed class RequiresDynamicCodeAttribute : Attribute
26 | {
27 | ///
28 | /// Initializes a new instance of the class
29 | /// with the specified message.
30 | ///
31 | ///
32 | /// A message that contains information about the usage of dynamic code.
33 | ///
34 | public RequiresDynamicCodeAttribute(string message)
35 | {
36 | Message = message;
37 | }
38 |
39 | ///
40 | /// Gets a message that contains information about the usage of dynamic code.
41 | ///
42 | public string Message { get; }
43 |
44 | ///
45 | /// Gets or sets an optional URL that contains more information about the method,
46 | /// why it requires dynamic code, and what options a consumer has to deal with it.
47 | ///
48 | public string? Url { get; set; }
49 | }
50 |
51 | #endif
52 | #endif
53 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs:
--------------------------------------------------------------------------------
1 | #if NET5_0_OR_GREATER
2 |
3 | #if POLYKIT_PUBLIC
4 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute))]
5 | #endif
6 |
7 | #else
8 |
9 | // Licensed to the .NET Foundation under one or more agreements.
10 | // The .NET Foundation licenses this file to you under the MIT license.
11 | namespace System.Diagnostics.CodeAnalysis;
12 |
13 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs
14 |
15 | ///
16 | /// Indicates that the specified method requires dynamic access to code that is not referenced
17 | /// statically, for example through .
18 | ///
19 | ///
20 | /// This allows tools to understand which methods are unsafe to call when removing unreferenced
21 | /// code from an application.
22 | ///
23 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
24 | public // polyfill!
25 | sealed class RequiresUnreferencedCodeAttribute : Attribute
26 | {
27 | ///
28 | /// Initializes a new instance of the class
29 | /// with the specified message.
30 | ///
31 | ///
32 | /// A message that contains information about the usage of unreferenced code.
33 | ///
34 | public RequiresUnreferencedCodeAttribute(string message)
35 | {
36 | Message = message;
37 | }
38 |
39 | ///
40 | /// Gets a message that contains information about the usage of unreferenced code.
41 | ///
42 | public string Message { get; }
43 |
44 | ///
45 | /// Gets or sets an optional URL that contains more information about the method,
46 | /// why it requires unreferenced code, and what options a consumer has to deal with it.
47 | ///
48 | public string? Url { get; set; }
49 | }
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs:
--------------------------------------------------------------------------------
1 | #if POLYKIT_NETSDK7_0_OR_GREATER
2 | #if NET7_0_OR_GREATER
3 |
4 | #if POLYKIT_PUBLIC
5 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute))]
6 | #endif
7 |
8 | #else
9 |
10 | // Licensed to the .NET Foundation under one or more agreements.
11 | // The .NET Foundation licenses this file to you under the MIT license.
12 | namespace System.Diagnostics.CodeAnalysis;
13 |
14 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs
15 |
16 | ///
17 | /// Specifies that this constructor sets all required members for the current type, and callers
18 | /// do not need to set any required members themselves.
19 | ///
20 | [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
21 | public // polyfill!
22 | sealed class SetsRequiredMembersAttribute : Attribute
23 | {
24 | }
25 |
26 | #endif
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/PolyKit.Polyfills/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs:
--------------------------------------------------------------------------------
1 | #if POLYKIT_NETSDK7_0_OR_GREATER
2 | #if NET7_0_OR_GREATER
3 |
4 | #if POLYKIT_PUBLIC
5 | [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute))]
6 | #endif
7 |
8 | #else
9 |
10 | // Licensed to the .NET Foundation under one or more agreements.
11 | // The .NET Foundation licenses this file to you under the MIT license.
12 | namespace System.Diagnostics.CodeAnalysis;
13 |
14 | // https://github.com/dotnet/runtime/blob/v8.0.0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs
15 |
16 | /// Specifies the syntax used in a string.
17 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
18 | public // polyfill!
19 | sealed class StringSyntaxAttribute : Attribute
20 | {
21 | /// The syntax identifier for strings containing composite formats for string formatting.
22 | public const string CompositeFormat = nameof(CompositeFormat);
23 |
24 | /// The syntax identifier for strings containing date format specifiers.
25 | public const string DateOnlyFormat = nameof(DateOnlyFormat);
26 |
27 | /// The syntax identifier for strings containing date and time format specifiers.
28 | public const string DateTimeFormat = nameof(DateTimeFormat);
29 |
30 | /// The syntax identifier for strings containing format specifiers.
31 | public const string EnumFormat = nameof(EnumFormat);
32 |
33 | /// The syntax identifier for strings containing format specifiers.
34 | public const string GuidFormat = nameof(GuidFormat);
35 |
36 | /// The syntax identifier for strings containing JavaScript Object Notation (JSON).
37 | public const string Json = nameof(Json);
38 |
39 | /// The syntax identifier for strings containing numeric format specifiers.
40 | public const string NumericFormat = nameof(NumericFormat);
41 |
42 | /// The syntax identifier for strings containing regular expressions.
43 | public const string Regex = nameof(Regex);
44 |
45 | /// The syntax identifier for strings containing time format specifiers.
46 | public const string TimeOnlyFormat = nameof(TimeOnlyFormat);
47 |
48 | /// The syntax identifier for strings containing format specifiers.
49 | public const string TimeSpanFormat = nameof(TimeSpanFormat);
50 |
51 | /// The syntax identifier for strings containing URIs.
52 | public const string Uri = nameof(Uri);
53 |
54 | /// The syntax identifier for strings containing XML.
55 | public const string Xml = nameof(Xml);
56 |
57 | /// Initializes a new instance of the class
58 | /// with the identifier of the syntax used.
59 | /// The syntax identifier.
60 | public StringSyntaxAttribute(string syntax)
61 | {
62 | Syntax = syntax;
63 | Arguments = Array.Empty