From bec267092ee09dd14032a6d08eae1be22d9858c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20S=C3=A1nchez=20L=C3=B3pez?=
<1175054+carlossanlop@users.noreply.github.com>
Date: Tue, 15 Aug 2023 09:37:55 -0700
Subject: [PATCH 001/345] [release/8.0] Bump to RC2 (#90557)
* [release/8.0] Bump to RC2
Bump the base release/8.0 branch to target RC2.
* Set prerelease to 0 in configureplatform.make
---
eng/Versions.props | 2 +-
eng/native/configureplatform.cmake | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/eng/Versions.props b/eng/Versions.props
index 3cccff5761371c..8b6faffed23598 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -10,7 +10,7 @@
7.0.86.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet7)').Build),11))rc
- 1
+ 2-$(PreReleaseVersionLabel).$(PreReleaseVersionIteration)$(SdkBandVersion)$(WorkloadVersionSuffix)
-
+ falsetrue
- 113.0.5672.63
- 1121455
- <_ChromeBaseSnapshotUrl>https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1121461
+ 115.0.5790.170
+ 1148114
+ <_ChromeBaseSnapshotUrl>https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/1148123
- 113.0.5672.64
- 1121455
- <_ChromeBaseSnapshotUrl>https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1121477
+ 115.0.5790.171
+ 1148114
+ <_ChromeBaseSnapshotUrl>https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1148119
From 94f0a7167cfd8fdf9387e57045473190281e1bb9 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 15 Aug 2023 18:24:12 -0700
Subject: [PATCH 007/345] [release/8.0-rc1] [mono][ios] Revert LLVM mode for
apple mobile tests (#90624)
* Revert LLVM mode for apple mobile tests
* Add comment
---------
Co-authored-by: Milos Kotlar
---
eng/testing/tests.ioslike.targets | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/eng/testing/tests.ioslike.targets b/eng/testing/tests.ioslike.targets
index 9151c7c7db05e5..f93afcf1dfb31b 100644
--- a/eng/testing/tests.ioslike.targets
+++ b/eng/testing/tests.ioslike.targets
@@ -15,8 +15,8 @@
<_AOTBuildCommand Condition="'$(ContinuousIntegrationBuild)' != 'true'">$(_AOTBuildCommand) /p:RuntimeSrcDir=$(RepoRoot) /p:RuntimeConfig=$(Configuration)
-
- <_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR="$XHARNESS_EXECUTION_DIR" /p:RunAOTCompilation=$(RunAOTCompilation) /p:UseNativeAOTRuntime=$(UseNativeAOTRuntime) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=true /p:Configuration=$(Configuration)
+
+ <_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR="$XHARNESS_EXECUTION_DIR" /p:RunAOTCompilation=$(RunAOTCompilation) /p:UseNativeAOTRuntime=$(UseNativeAOTRuntime) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:MonoEnableLLVM=true /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=true /p:Configuration=$(Configuration)
<_AOTBuildCommand>$(_AOTBuildCommand)
<_ResetSimulatorSwitch Condition="'$(TargetOS)' == 'iossimulator' or '$(TargetOS)' == 'tvossimulator'">--reset-simulator
From 6222fca7914de6790a96079c75021b8263a87ad0 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 15 Aug 2023 21:50:33 -0700
Subject: [PATCH 008/345] [release/8.0-rc1] [workloads] Put quotes around
GetFileName call when collecting telemetry (#90606)
* [workloads] Put quotes around GetFileName call when collecting telemetry
There are cases where `%(ReferencePath)` is empty, so prevent exceptions by quoting the value.
Fixes https://github.com/dotnet/runtime/issues/90584
* Feedback
---------
Co-authored-by: Steve Pfister
Co-authored-by: Steve Pfister
---
.../WorkloadTelemetry.targets | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
index f9cd6efe170a2c..8f78ce16b62587 100644
--- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
+++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
@@ -38,8 +38,8 @@
- <_WorkloadUsesOther Condition="'$([System.IO.Path]::GetFileName(%(ReferencePath.Identity)).ToLower())' == 'avalonia.dll'">true
- <_WorkloadUsesOther Condition="'$([System.IO.Path]::GetFileName(%(ReferencePath.Identity)).ToLower())' == 'uno.dll'">true
+ <_WorkloadUsesOther Condition="'$([System.IO.Path]::GetFileName("%(ReferencePath.Identity)").ToLowerInvariant())' == 'avalonia.dll'">true
+ <_WorkloadUsesOther Condition="'$([System.IO.Path]::GetFileName("%(ReferencePath.Identity)").ToLowerInvariant())' == 'uno.dll'">true
<_WorkloadUsesMobileSDKOnly Condition="'$(RuntimeIdentifier)' != 'browser-wasm' and '$(UseMaui)' != 'true' and '$(_WorkloadUsesOther)' != 'true'">true
From b1225e7c0902f82362afc9cc21b632462a9339b4 Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
<42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Wed, 16 Aug 2023 07:17:22 -0700
Subject: [PATCH 009/345] Update dependencies from
https://github.com/dotnet/emsdk build 20230815.5 (#90649)
Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100.Transport
From Version 8.0.0-rc.1.23411.2 -> To Version 8.0.0-rc.1.23415.5
Co-authored-by: dotnet-maestro[bot]
---
eng/Version.Details.xml | 4 ++--
eng/Versions.props | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 76bf5019cd8ed2..e31341152d13b0 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -90,9 +90,9 @@
2f4ef297939628143389ddeea569874ded0b1c1b
-
+ https://github.com/dotnet/emsdk
- abfa03c97f4175d4d209435cd0e71f558e36c3fd
+ 66dbaefff04250dc72849f0172e0c53bcfb3ab38
diff --git a/eng/Versions.props b/eng/Versions.props
index 3cccff5761371c..ff21c1ee1f07dc 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -238,7 +238,7 @@
Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml
like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-8_0_100_Transport
-->
- 8.0.0-rc.1.23411.2
+ 8.0.0-rc.1.23415.5$(MicrosoftNETWorkloadEmscriptenCurrentManifest80100TransportVersion)1.1.87-gba258badda
From b33c596d0dd56b509ad4ad144985d00e21d08035 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 16 Aug 2023 07:26:12 -0700
Subject: [PATCH 010/345] [release/8.0] Return false from ComWrappers.Try...
methods (#90635)
* Return false from ComWrappers.Try... methods
Return false from ComWrappers.TryGetComInstance/TryGetObject instead of
throwing PNSE. It saves callers from needing to protect against PNSE.
Fix #90311
* More efficient IsWindows check
---------
Co-authored-by: Jan Kotas
---
.../src/System/ComponentModel/TypeDescriptor.cs | 2 +-
.../InteropServices/ComWrappers.PlatformNotSupported.cs | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
index 874fa6e2e7d03e..2efd53e6223ae7 100644
--- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
+++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
@@ -1542,7 +1542,7 @@ private static TypeDescriptionNode NodeFor(object instance, bool createDelegator
{
type = ComObjectType;
}
- else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
+ else if (OperatingSystem.IsWindows()
&& ComWrappers.TryGetComInstance(instance, out nint unknown))
{
// ComObjectType uses the Windows Forms provided ComNativeDescriptor. It currently has hard Win32
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs
index 2d2a812cb41a07..37c25f851538a7 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs
@@ -11,12 +11,14 @@ public abstract partial class ComWrappers
{
public static unsafe bool TryGetComInstance(object obj, out IntPtr unknown)
{
- throw new PlatformNotSupportedException();
+ unknown = default;
+ return false;
}
public static unsafe bool TryGetObject(IntPtr unknown, [NotNullWhen(true)] out object? obj)
{
- throw new PlatformNotSupportedException();
+ obj = default;
+ return false;
}
public partial struct ComInterfaceDispatch
From d29067bc3bc614ed08a5e6cd94baff0481f435e6 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 16 Aug 2023 07:38:41 -0700
Subject: [PATCH 011/345] [release/8.0-rc1] Fix support for non-public default
constructors using JsonIncludeAttribute (#90615)
* Fix support for non-public constructors using JsonIncludeAttribute
* Address feedback.
---------
Co-authored-by: Eirik Tsarpalis
---
.../DefaultJsonTypeInfoResolver.Helpers.cs | 21 ++++++++++++++-
.../Serialization/Metadata/MemberAccessor.cs | 5 ++--
.../ReflectionEmitCachingMemberAccessor.cs | 6 ++---
.../Metadata/ReflectionEmitMemberAccessor.cs | 15 ++++++-----
.../Metadata/ReflectionMemberAccessor.cs | 27 +++++++------------
.../ConstructorTests.AttributePresence.cs | 18 +++++++++++++
.../TestClasses/TestClasses.Constructor.cs | 27 +++++++++++++++++++
.../Serialization/ConstructorTests.cs | 6 +++++
8 files changed, 95 insertions(+), 30 deletions(-)
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs
index 7ec9db9adc7739..8ee9f3db0283b4 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Helpers.cs
@@ -49,7 +49,7 @@ private static JsonTypeInfo CreateTypeInfoCore(Type type, JsonConverter converte
typeInfo.PopulatePolymorphismMetadata();
typeInfo.MapInterfaceTypesToCallbacks();
- Func
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/xliff-tasks
- 493329204079519072f0241ed26f692bdee0d60c
+ 649a1e75101b701d753ee41efbe9038f9b23a0db
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8d
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8dhttps://github.com/dotnet/runtime-assets
@@ -330,9 +330,9 @@
https://github.com/dotnet/xharness480b9159eb7e69b182a87581d5a336e97e0b6dae
-
+ https://github.com/dotnet/arcade
- 9b2af35a6702526dc8a7c5fcadcc44efd0dca170
+ 46ff142f43e887d5f9a4d87ef39d72166f61db8dhttps://dev.azure.com/dnceng/internal/_git/dotnet-optimization
diff --git a/eng/Versions.props b/eng/Versions.props
index d75c6567090d01..fd3e699e214032 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -85,21 +85,21 @@
8.0.100-preview.7.23329.3
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 2.5.1-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
- 8.0.0-beta.23411.1
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 2.5.1-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.4
+ 8.0.0-beta.23415.46.0.0-preview.1.102
diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1
index 2dc86ea2cdda1a..6c65e81925f2a3 100644
--- a/eng/common/SetupNugetSources.ps1
+++ b/eng/common/SetupNugetSources.ps1
@@ -2,7 +2,7 @@
# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080
#
# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry
-# under for each Maestro managed private feed. Two additional credential
+# under for each Maestro managed private feed. Two additional credential
# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport.
#
# This script needs to be called in every job that will restore packages and which the base repo has
@@ -37,7 +37,7 @@ Set-StrictMode -Version 2.0
# Add source entry to PackageSources
function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Username, $Password) {
$packageSource = $sources.SelectSingleNode("add[@key='$SourceName']")
-
+
if ($packageSource -eq $null)
{
$packageSource = $doc.CreateElement("add")
@@ -48,7 +48,7 @@ function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Usern
else {
Write-Host "Package source $SourceName already present."
}
-
+
AddCredential -Creds $creds -Source $SourceName -Username $Username -Password $Password
}
@@ -89,7 +89,7 @@ function InsertMaestroPrivateFeedCredentials($Sources, $Creds, $Username, $Passw
$maestroPrivateSources = $Sources.SelectNodes("add[contains(@key,'darc-int')]")
Write-Host "Inserting credentials for $($maestroPrivateSources.Count) Maestro's private feeds."
-
+
ForEach ($PackageSource in $maestroPrivateSources) {
Write-Host "`tInserting credential for Maestro's feed:" $PackageSource.Key
AddCredential -Creds $creds -Source $PackageSource.Key -Username $Username -Password $Password
diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh
index a8bb8acd3be180..d387c7eac95e54 100644
--- a/eng/common/SetupNugetSources.sh
+++ b/eng/common/SetupNugetSources.sh
@@ -4,7 +4,7 @@
# This file should be removed as part of this issue: https://github.com/dotnet/arcade/issues/4080
#
# What the script does is iterate over all package sources in the pointed NuGet.config and add a credential entry
-# under for each Maestro's managed private feed. Two additional credential
+# under for each Maestro's managed private feed. Two additional credential
# entries are also added for the two private static internal feeds: dotnet3-internal and dotnet3-internal-transport.
#
# This script needs to be called in every job that will restore packages and which the base repo has
@@ -68,7 +68,7 @@ if [ "$?" != "0" ]; then
sed -i.bak "s|$ConfigNodeHeader|$ConfigNodeHeader${NL}$PackageSourcesTemplate|" $ConfigFile
fi
-# Ensure there is a ... section.
+# Ensure there is a ... section.
grep -i "" $ConfigFile
if [ "$?" != "0" ]; then
echo "Adding ... section."
@@ -142,7 +142,7 @@ IFS=$PrevIFS
for FeedName in ${PackageSources[@]} ; do
# Check if there is no existing credential for this FeedName
- grep -i "<$FeedName>" $ConfigFile
+ grep -i "<$FeedName>" $ConfigFile
if [ "$?" != "0" ]; then
echo "Adding credentials for $FeedName."
diff --git a/eng/common/native/init-distro-rid.sh b/eng/common/native/init-distro-rid.sh
index aba9fe24028b0f..de1687b2ccbe79 100644
--- a/eng/common/native/init-distro-rid.sh
+++ b/eng/common/native/init-distro-rid.sh
@@ -79,7 +79,6 @@ getNonPortableDistroRid()
# Input:
# os: (str)
# arch: (str)
-# isPortable: (int)
# rootfsDir?: (nullable:string)
#
# Return:
@@ -97,10 +96,9 @@ initDistroRidGlobal()
{
local targetOs="$1"
local targetArch="$2"
- local isPortable="$3"
local rootfsDir=""
- if [ "$#" -ge 4 ]; then
- rootfsDir="$4"
+ if [ "$#" -ge 3 ]; then
+ rootfsDir="$3"
fi
if [ -n "${rootfsDir}" ]; then
diff --git a/eng/common/sdl/trim-assets-version.ps1 b/eng/common/sdl/trim-assets-version.ps1
new file mode 100644
index 00000000000000..d8cfec910c77e6
--- /dev/null
+++ b/eng/common/sdl/trim-assets-version.ps1
@@ -0,0 +1,75 @@
+<#
+.SYNOPSIS
+Install and run the 'Microsoft.DotNet.VersionTools.Cli' tool with the 'trim-artifacts-version' command to trim the version from the NuGet assets file name.
+
+.PARAMETER InputPath
+Full path to directory where artifact packages are stored
+
+.PARAMETER Recursive
+Search for NuGet packages recursively
+
+#>
+
+Param(
+ [string] $InputPath,
+ [bool] $Recursive = $true
+)
+
+$CliToolName = "Microsoft.DotNet.VersionTools.Cli"
+
+function Install-VersionTools-Cli {
+ param(
+ [Parameter(Mandatory=$true)][string]$Version
+ )
+
+ Write-Host "Installing the package '$CliToolName' with a version of '$version' ..."
+ $feed = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json"
+
+ $argumentList = @("tool", "install", "--local", "$CliToolName", "--add-source $feed", "--no-cache", "--version $Version")
+ Start-Process "$dotnet" -Verbose -ArgumentList $argumentList -NoNewWindow -Wait
+}
+
+# -------------------------------------------------------------------
+
+if (!(Test-Path $InputPath)) {
+ Write-Host "Input Path '$InputPath' does not exist"
+ ExitWithExitCode 1
+}
+
+$ErrorActionPreference = 'Stop'
+Set-StrictMode -Version 2.0
+
+$disableConfigureToolsetImport = $true
+$global:LASTEXITCODE = 0
+
+# `tools.ps1` checks $ci to perform some actions. Since the SDL
+# scripts don't necessarily execute in the same agent that run the
+# build.ps1/sh script this variable isn't automatically set.
+$ci = $true
+. $PSScriptRoot\..\tools.ps1
+
+try {
+ $dotnetRoot = InitializeDotNetCli -install:$true
+ $dotnet = "$dotnetRoot\dotnet.exe"
+
+ $toolsetVersion = Read-ArcadeSdkVersion
+ Install-VersionTools-Cli -Version $toolsetVersion
+
+ $cliToolFound = (& "$dotnet" tool list --local | Where-Object {$_.Split(' ')[0] -eq $CliToolName})
+ if ($null -eq $cliToolFound) {
+ Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "The '$CliToolName' tool is not installed."
+ ExitWithExitCode 1
+ }
+
+ Exec-BlockVerbosely {
+ & "$dotnet" $CliToolName trim-assets-version `
+ --assets-path $InputPath `
+ --recursive $Recursive
+ Exit-IfNZEC "Sdl"
+ }
+}
+catch {
+ Write-Host $_
+ Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_
+ ExitWithExitCode 1
+}
\ No newline at end of file
diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1
index c9eced9f7df4c6..aa74ab4a81e782 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -671,6 +671,10 @@ function InitializeNativeTools() {
}
}
+function Read-ArcadeSdkVersion() {
+ return $GlobalJson.'msbuild-sdks'.'Microsoft.DotNet.Arcade.Sdk'
+}
+
function InitializeToolset() {
if (Test-Path variable:global:_ToolsetBuildProj) {
return $global:_ToolsetBuildProj
@@ -678,7 +682,7 @@ function InitializeToolset() {
$nugetCache = GetNuGetPackageCachePath
- $toolsetVersion = $GlobalJson.'msbuild-sdks'.'Microsoft.DotNet.Arcade.Sdk'
+ $toolsetVersion = Read-ArcadeSdkVersion
$toolsetLocationFile = Join-Path $ToolsetDir "$toolsetVersion.txt"
if (Test-Path $toolsetLocationFile) {
diff --git a/global.json b/global.json
index b4ca83d356c283..cf4ac698e3e8cb 100644
--- a/global.json
+++ b/global.json
@@ -8,9 +8,9 @@
"dotnet": "8.0.100-preview.7.23376.3"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23411.1",
- "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23411.1",
- "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.23411.1",
+ "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23415.4",
+ "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23415.4",
+ "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.23415.4",
"Microsoft.Build.NoTargets": "3.7.0",
"Microsoft.Build.Traversal": "3.4.0",
"Microsoft.NET.Sdk.IL": "8.0.0-rc.1.23406.6"
From a9b1d3c86611b0e49bedec766ebe1110e1ac1b9f Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 09:25:09 -0600
Subject: [PATCH 027/345] Fix PortableRuntimeIdentifierGraph.json not found
during runtime repo source build (#90714)
Co-authored-by: Elinor Fung
---
eng/liveBuilds.targets | 6 ------
1 file changed, 6 deletions(-)
diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets
index 118601229cf8b7..370e19805cc3a0 100644
--- a/eng/liveBuilds.targets
+++ b/eng/liveBuilds.targets
@@ -260,10 +260,4 @@
DependsOnTargets="
ResolveLibrariesRefAssembliesFromLocalBuild;
ResolveLibrariesRuntimeFilesFromLocalBuild" />
-
-
-
- $([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Microsoft.NETCore.Platforms', 'runtime.json'))
- $([MSBuild]::NormalizePath('$(LibrariesProjectRoot)', 'Microsoft.NETCore.Platforms', 'src', 'runtime.json'))
-
From 3924341ea7216d9b313d5d8e0590fbd3dca4be00 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 09:44:10 -0700
Subject: [PATCH 028/345] Release the stream once the response is sent (#90722)
Co-authored-by: ManickaP
---
.../Net/Http/Http3LoopbackConnection.cs | 38 +++++++++++++------
1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs
index ec5c7a022c65a6..9d6fef5fb3a720 100644
--- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs
+++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs
@@ -108,11 +108,6 @@ public static int GetRequestId(QuicStream stream)
return checked((int)stream.Id + 1);
}
- public Http3LoopbackStream GetOpenRequest(int requestId = 0)
- {
- return requestId == 0 ? _currentStream : _openStreams[requestId - 1];
- }
-
public override Task InitializeConnectionAsync()
{
throw new NotImplementedException();
@@ -195,6 +190,17 @@ public async Task EstablishControlStreamAsync(SettingsEntry[] settingsEntries)
await _outboundControlStream.SendSettingsFrameAsync(settingsEntries);
}
+ public async Task DisposeCurrentStream()
+ {
+ Assert.NotNull(_currentStream);
+ Assert.True(_currentStreamId >= 0);
+
+ await _currentStream.DisposeAsync().ConfigureAwait(false);
+ _openStreams.Remove((int)_currentStreamId);
+ _currentStream = null;
+ _currentStreamId = -4;
+ }
+
public override async Task ReadRequestBodyAsync()
{
return await _currentStream.ReadRequestBodyAsync().ConfigureAwait(false);
@@ -206,24 +212,32 @@ public override async Task ReadRequestDataAsync(bool readBody =
return await stream.ReadRequestDataAsync(readBody).ConfigureAwait(false);
}
- public override Task SendResponseAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList headers = null, string content = "", bool isFinal = true)
+ public override async Task SendResponseAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList headers = null, string content = "", bool isFinal = true)
{
- return GetOpenRequest().SendResponseAsync(statusCode, headers, content, isFinal);
+ await _currentStream.SendResponseAsync(statusCode, headers, content, isFinal);
+ if (isFinal)
+ {
+ await DisposeCurrentStream().ConfigureAwait(false);
+ }
}
- public override Task SendResponseBodyAsync(byte[] content, bool isFinal = true)
+ public override async Task SendResponseBodyAsync(byte[] content, bool isFinal = true)
{
- return GetOpenRequest().SendResponseBodyAsync(content, isFinal);
+ await _currentStream.SendResponseBodyAsync(content, isFinal);
+ if (isFinal)
+ {
+ await DisposeCurrentStream().ConfigureAwait(false);
+ }
}
public override Task SendResponseHeadersAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList headers = null)
{
- return GetOpenRequest().SendResponseHeadersAsync(statusCode, headers);
+ return _currentStream.SendResponseHeadersAsync(statusCode, headers);
}
public override Task SendPartialResponseHeadersAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList headers = null)
{
- return GetOpenRequest().SendPartialResponseHeadersAsync(statusCode, headers);
+ return _currentStream.SendPartialResponseHeadersAsync(statusCode, headers);
}
public override async Task HandleRequestAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList headers = null, string content = "")
@@ -310,7 +324,7 @@ public async Task WaitForClientDisconnectAsync(bool refuseNewRequests = true)
public override async Task WaitForCancellationAsync(bool ignoreIncomingData = true)
{
- await GetOpenRequest().WaitForCancellationAsync(ignoreIncomingData).ConfigureAwait(false);
+ await _currentStream.WaitForCancellationAsync(ignoreIncomingData).ConfigureAwait(false);
}
public override Task WaitForCloseAsync(CancellationToken cancellationToken)
From e20cc4e3e4e90540659b78c8938aba3c2238fae7 Mon Sep 17 00:00:00 2001
From: Matt Mitchell
Date: Thu, 17 Aug 2023 10:02:09 -0700
Subject: [PATCH 029/345] Call SetupNuGetSources for installer jobs (#90754)
---
eng/pipelines/installer/jobs/build-job.yml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/eng/pipelines/installer/jobs/build-job.yml b/eng/pipelines/installer/jobs/build-job.yml
index 5a0e37157e45c5..04be011a540758 100644
--- a/eng/pipelines/installer/jobs/build-job.yml
+++ b/eng/pipelines/installer/jobs/build-job.yml
@@ -296,6 +296,25 @@ jobs:
- checkout: self
clean: true
fetchDepth: $(checkoutFetchDepth)
+
+ - ${{ if ne(variables['System.TeamProject'], 'public') }}:
+ - ${{ if ne(parameters.osGroup, 'windows') }}:
+ - task: Bash@3
+ displayName: Setup Private Feeds Credentials
+ inputs:
+ filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh
+ arguments: $(Build.SourcesDirectory)/NuGet.config $Token
+ env:
+ Token: $(dn-bot-dnceng-artifact-feeds-rw)
+ - ${{ else }}:
+ - task: PowerShell@2
+ displayName: Setup Private Feeds Credentials
+ inputs:
+ filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
+ arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
+ env:
+ Token: $(dn-bot-dnceng-artifact-feeds-rw)
+
- ${{ if ne(parameters.liveRuntimeBuildConfig, '') }}:
- template: /eng/pipelines/common/download-artifact-step.yml
parameters:
From 3ab4246e5a3913786dd846da5cbbfa96435a3243 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 10:27:20 -0700
Subject: [PATCH 030/345] [release/8.0] JIT: Disallow mismatched GC-ness for
physical promotions (#90739)
* JIT: Disallow mismatched GC-ness for physical promotions
Physical promotion was working under the assumption that reinterpreting
GC pointers is undefined behavior, and would happily promote GC pointers
as integers if it saw such accesses. However, physical promotion is
function wide while the UB accesses can be happening in a restricted
(dynamically unreachable) scope. This exact situation happens in
MemoryExtensions.Contains. The issue was uncovered under jit stress
where we did not fold away the guard early enough, meaning that
promotion then saw a `TYP_LONG` access of a `struct { object, int }` and
proceeded to promote it as such.
Fix #90602
* Address feedback
---------
Co-authored-by: Jakob Botsch Nielsen
---
src/coreclr/jit/layout.cpp | 34 ++++++++++++++++++++++++++++++++
src/coreclr/jit/layout.h | 2 ++
src/coreclr/jit/promotion.cpp | 37 ++++++++++++++++++++++++++++++++---
3 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/src/coreclr/jit/layout.cpp b/src/coreclr/jit/layout.cpp
index 113414ddfd7f7a..918fd4ab6521d4 100644
--- a/src/coreclr/jit/layout.cpp
+++ b/src/coreclr/jit/layout.cpp
@@ -421,6 +421,7 @@ void ClassLayout::InitializeGCPtrs(Compiler* compiler)
//
// Return value:
// true if at least one GC ByRef, false otherwise.
+//
bool ClassLayout::HasGCByRef() const
{
unsigned slots = GetSlotCount();
@@ -435,6 +436,39 @@ bool ClassLayout::HasGCByRef() const
return false;
}
+//------------------------------------------------------------------------
+// IntersectsGCPtr: check if the specified interval intersects with a GC
+// pointer.
+//
+// Parameters:
+// offset - The start offset of the interval
+// size - The size of the interval
+//
+// Return value:
+// True if it does.
+//
+bool ClassLayout::IntersectsGCPtr(unsigned offset, unsigned size) const
+{
+ if (!HasGCPtr())
+ {
+ return false;
+ }
+
+ unsigned startSlot = offset / TARGET_POINTER_SIZE;
+ unsigned endSlot = (offset + size - 1) / TARGET_POINTER_SIZE;
+ assert((startSlot < GetSlotCount()) && (endSlot < GetSlotCount()));
+
+ for (unsigned i = startSlot; i <= endSlot; i++)
+ {
+ if (IsGCPtr(i))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
//------------------------------------------------------------------------
// AreCompatible: check if 2 layouts are the same for copying.
//
diff --git a/src/coreclr/jit/layout.h b/src/coreclr/jit/layout.h
index 0e9d6ed65d03d3..59ecaa9405485d 100644
--- a/src/coreclr/jit/layout.h
+++ b/src/coreclr/jit/layout.h
@@ -216,6 +216,8 @@ class ClassLayout
}
}
+ bool IntersectsGCPtr(unsigned offset, unsigned size) const;
+
static bool AreCompatible(const ClassLayout* layout1, const ClassLayout* layout2);
private:
diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp
index e2c4e797a3c9d8..5982ed79283355 100644
--- a/src/coreclr/jit/promotion.cpp
+++ b/src/coreclr/jit/promotion.cpp
@@ -621,6 +621,38 @@ class LocalUses
bool EvaluateReplacement(
Compiler* comp, unsigned lclNum, const Access& access, unsigned inducedCount, weight_t inducedCountWtd)
{
+ // Verify that this replacement has proper GC ness compared to the
+ // layout. While reinterpreting GC fields to integers can be considered
+ // UB, there are scenarios where it can happen safely:
+ //
+ // * The user code could have guarded the access with a dynamic check
+ // that it doesn't contain a GC pointer, so that the access is actually
+ // in dead code. This happens e.g. in span functions in SPC.
+ //
+ // * For byrefs, reinterpreting as an integer could be ok in a
+ // restricted scope due to pinning.
+ //
+ // In theory we could allow these promotions in the restricted scope,
+ // but currently physical promotion works on a function-wide basis.
+
+ LclVarDsc* lcl = comp->lvaGetDesc(lclNum);
+ ClassLayout* layout = lcl->GetLayout();
+ if (layout->IntersectsGCPtr(access.Offset, genTypeSize(access.AccessType)))
+ {
+ if (((access.Offset % TARGET_POINTER_SIZE) != 0) ||
+ (layout->GetGCPtrType(access.Offset / TARGET_POINTER_SIZE) != access.AccessType))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (varTypeIsGC(access.AccessType))
+ {
+ return false;
+ }
+ }
+
unsigned countOverlappedCallArg = 0;
unsigned countOverlappedStoredFromCall = 0;
@@ -678,9 +710,8 @@ class LocalUses
// Now look at the overlapping struct uses that promotion will make more expensive.
- unsigned countReadBacks = 0;
- weight_t countReadBacksWtd = 0;
- LclVarDsc* lcl = comp->lvaGetDesc(lclNum);
+ unsigned countReadBacks = 0;
+ weight_t countReadBacksWtd = 0;
// For parameters or OSR locals we always need one read back.
if (lcl->lvIsParam || lcl->lvIsOSRLocal)
{
From 77884726ecf744ea5bb2037b7cb52f0ed1ed6bc5 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 10:55:24 -0700
Subject: [PATCH 031/345] [wasm] Pin sdk version to 8.0.100-rc.1.23415.5 for
workload testing (#90748)
.. because `dotnet-install --channel 8.0` is returning 9.0-alpha sdks right now.
Co-authored-by: Ankit Jain
---
eng/Versions.props | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/Versions.props b/eng/Versions.props
index fd3e699e214032..760c9e8b76e3f7 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -206,7 +206,7 @@
2.45.02.45.0
-
+ 8.0.100-rc.1.23415.51.1.2-beta1.23323.17.0.0-preview-20221010.1
From 38a117099c2bc6e32c9fb3eaec324450448128eb Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 14:33:37 -0700
Subject: [PATCH 032/345] Expose TC_* vars (#90761)
Co-authored-by: EgorBo
---
src/coreclr/inc/clrconfigvalues.h | 5 +++--
src/coreclr/vm/eeconfig.cpp | 8 +++++---
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h
index ed61a56b976d26..7b356b07443999 100644
--- a/src/coreclr/inc/clrconfigvalues.h
+++ b/src/coreclr/inc/clrconfigvalues.h
@@ -574,9 +574,10 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.")
#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_AggressiveTiering, W("TC_AggressiveTiering"), 0, "Transition through tiers aggressively.")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), TC_CallCountThreshold, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), TC_CallCountingDelayMs, "A perpetual delay in milliseconds that is applied to call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.")
+
RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_BackgroundWorkerTimeoutMs, W("TC_BackgroundWorkerTimeoutMs"), TC_BackgroundWorkerTimeoutMs, "How long in milliseconds the background worker thread may remain idle before exiting.")
-RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), TC_CallCountThreshold, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.")
-RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), TC_CallCountingDelayMs, "A perpetual delay in milliseconds that is applied to call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), TC_DelaySingleProcMultiplier, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCounting, W("TC_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_UseCallCountingStubs, W("TC_UseCallCountingStubs"), 1, "Uses call counting stubs for faster call counting.")
diff --git a/src/coreclr/vm/eeconfig.cpp b/src/coreclr/vm/eeconfig.cpp
index 417910eb183bc0..566a0c17ad4aa5 100644
--- a/src/coreclr/vm/eeconfig.cpp
+++ b/src/coreclr/vm/eeconfig.cpp
@@ -721,7 +721,8 @@ HRESULT EEConfig::sync()
fTieredCompilation_CallCounting = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_CallCounting) != 0;
DWORD tieredCompilation_ConfiguredCallCountThreshold =
- CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_CallCountThreshold);
+ Configuration::GetKnobDWORDValue(W("System.Runtime.TC_CallCountThreshold"), CLRConfig::EXTERNAL_TC_CallCountThreshold);
+
if (tieredCompilation_ConfiguredCallCountThreshold == 0)
{
tieredCompilation_CallCountThreshold = 1;
@@ -735,8 +736,9 @@ HRESULT EEConfig::sync()
tieredCompilation_CallCountThreshold = (UINT16)tieredCompilation_ConfiguredCallCountThreshold;
}
- tieredCompilation_CallCountingDelayMs = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_CallCountingDelayMs);
-
+ tieredCompilation_CallCountingDelayMs =
+ Configuration::GetKnobDWORDValue(W("System.Runtime.TC_CallCountingDelayMs"), CLRConfig::EXTERNAL_TC_CallCountingDelayMs);
+
bool hasSingleProcessor = GetCurrentProcessCpuCount() == 1;
if (hasSingleProcessor)
{
From 64dc1fc29a27a7d7139f7619a102bbfdc6f37253 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 14:35:36 -0700
Subject: [PATCH 033/345] Call SetupNuGetSources for installer jobs (#90759)
Co-authored-by: Matt Mitchell
---
eng/pipelines/installer/jobs/build-job.yml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/eng/pipelines/installer/jobs/build-job.yml b/eng/pipelines/installer/jobs/build-job.yml
index 5a0e37157e45c5..04be011a540758 100644
--- a/eng/pipelines/installer/jobs/build-job.yml
+++ b/eng/pipelines/installer/jobs/build-job.yml
@@ -296,6 +296,25 @@ jobs:
- checkout: self
clean: true
fetchDepth: $(checkoutFetchDepth)
+
+ - ${{ if ne(variables['System.TeamProject'], 'public') }}:
+ - ${{ if ne(parameters.osGroup, 'windows') }}:
+ - task: Bash@3
+ displayName: Setup Private Feeds Credentials
+ inputs:
+ filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh
+ arguments: $(Build.SourcesDirectory)/NuGet.config $Token
+ env:
+ Token: $(dn-bot-dnceng-artifact-feeds-rw)
+ - ${{ else }}:
+ - task: PowerShell@2
+ displayName: Setup Private Feeds Credentials
+ inputs:
+ filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
+ arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
+ env:
+ Token: $(dn-bot-dnceng-artifact-feeds-rw)
+
- ${{ if ne(parameters.liveRuntimeBuildConfig, '') }}:
- template: /eng/pipelines/common/download-artifact-step.yml
parameters:
From 515e5d1b905a86d2adfe8775a9b1ca215c8e535d Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 14:38:32 -0700
Subject: [PATCH 034/345] [release/8.0] Update Get/SetFieldValue to Account for
EnC (#90623)
* update Get/SetFieldValue
* get the address of the instance
* Update src/coreclr/vm/invokeutil.cpp
---------
Co-authored-by: Mikelle
Co-authored-by: Jan Kotas
---
src/coreclr/vm/invokeutil.cpp | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/coreclr/vm/invokeutil.cpp b/src/coreclr/vm/invokeutil.cpp
index c4ba804a4c493f..e6ed2103393e37 100644
--- a/src/coreclr/vm/invokeutil.cpp
+++ b/src/coreclr/vm/invokeutil.cpp
@@ -906,9 +906,13 @@ void InvokeUtil::SetValidField(CorElementType fldType,
{
void* pFieldData;
if (pField->IsStatic())
+ {
pFieldData = pField->GetCurrentStaticAddress();
+ }
else
- pFieldData = (*((BYTE**)target)) + pField->GetOffset() + sizeof(Object);
+ {
+ pFieldData = pField->GetInstanceAddress(*target);
+ }
if (*valueObj == NULL)
InitValueClass(pFieldData, pMT);
@@ -1049,9 +1053,12 @@ OBJECTREF InvokeUtil::GetFieldValue(FieldDesc* pField, TypeHandle fieldType, OBJ
GCPROTECT_BEGIN(obj);
// calculate the offset to the field...
if (pField->IsStatic())
+ {
p = pField->GetCurrentStaticAddress();
- else {
- p = (*((BYTE**)target)) + pField->GetOffset() + sizeof(Object);
+ }
+ else
+ {
+ p = pField->GetInstanceAddress(*target);
}
GCPROTECT_END();
From a2953d7ac31164d605434ceec911210c9cf74493 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 14:43:10 -0700
Subject: [PATCH 035/345] [release/8.0] [JIT] ARM64 - Temporary fix for ldp/stp
optimizations - with test fix (#90758)
* Added regression test 85765
* Mark M4 as NoInlining
* Check current and last ins format to determine whether to proceed with the optimized ldr/str pair
* Additional test
* Feedback
* Fix test
* Fixing test again...
---------
Co-authored-by: TIHan
---
src/coreclr/jit/emitarm64.cpp | 9 +++
.../JitBlue/Runtime_85765/Runtime_85765.cs | 63 +++++++++++++++++++
.../Runtime_85765/Runtime_85765.csproj | 9 +++
3 files changed, 81 insertions(+)
create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.cs
create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.csproj
diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp
index b4e81322e2a696..f01ad548d2ee04 100644
--- a/src/coreclr/jit/emitarm64.cpp
+++ b/src/coreclr/jit/emitarm64.cpp
@@ -16615,6 +16615,15 @@ emitter::RegisterOrder emitter::IsOptimizableLdrStrWithPair(
emitAttr prevSize = emitLastIns->idOpSize();
ssize_t prevImm = emitGetInsSC(emitLastIns);
+ // If we have this format, the 'imm' and/or 'prevImm' are not scaled(encoded),
+ // therefore we cannot proceed.
+ // TODO: In this context, 'imm' and 'prevImm' are assumed to be scaled(encoded).
+ // They should never be scaled(encoded) until its about to be written to the buffer.
+ if (fmt == IF_LS_2C || lastInsFmt == IF_LS_2C)
+ {
+ return eRO_none;
+ }
+
// Signed, *raw* immediate value fits in 7 bits, so for LDP/ STP the raw value is from -64 to +63.
// For LDR/ STR, there are 9 bits, so we need to limit the range explicitly in software.
if ((imm < -64) || (imm > 63) || (prevImm < -64) || (prevImm > 63))
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.cs b/src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.cs
new file mode 100644
index 00000000000000..89c22ae90dc821
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+public class Runtime_85765
+{
+ public struct S0
+ {
+ public S0(bool f1): this()
+ {
+ }
+ }
+
+ public struct S1
+ {
+ public byte F0;
+ public bool F1;
+ public bool F2;
+ }
+
+ [Fact]
+ public static void Test()
+ {
+ S1 vr2 = M4();
+ vr2.F2 |= vr2.F1;
+ Assert.False(Consume(vr2.F2));
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static S1 M4()
+ {
+ S1 var1 = default(S1);
+ var vr0 = new S0(false);
+ return var1;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Consume(bool value)
+ {
+ return value;
+ }
+
+ // ------
+
+ [Fact]
+ public unsafe static void Test2()
+ {
+ byte* bytes = stackalloc byte[1024];
+ bytes[0x1A] = 1;
+ bytes[0x1B] = 2;
+ int sum = Foo(bytes);
+ Assert.True(sum == 515);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public unsafe static int Foo(byte* b)
+ {
+ return Unsafe.ReadUnaligned(ref b[0x1A]) + Unsafe.ReadUnaligned(ref b[0x1B]);
+ }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.csproj
new file mode 100644
index 00000000000000..a4cc9d0594f93e
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_85765/Runtime_85765.csproj
@@ -0,0 +1,9 @@
+
+
+ True
+ True
+
+
+
+
+
From e64cdbb17b1023f30d1349badc4e045ded3a7a15 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 14:49:13 -0700
Subject: [PATCH 036/345] [release/8.0] Switch fx_ver_t::as_str from
stringstream to append/to_string (#90760)
* Switch fx_ver_t::as_str from stringstream to append/to_string
* Switch version_t::as_str
* Remove unnecessary include
---------
Co-authored-by: Elinor Fung
---
src/native/corehost/fxr/fx_ver.cpp | 31 ++++++--------------
src/native/corehost/fxr/fx_ver.h | 2 --
src/native/corehost/hostmisc/pal.unix.cpp | 1 -
src/native/corehost/hostmisc/pal.windows.cpp | 1 -
src/native/corehost/hostpolicy/version.cpp | 16 +++++-----
5 files changed, 18 insertions(+), 33 deletions(-)
diff --git a/src/native/corehost/fxr/fx_ver.cpp b/src/native/corehost/fxr/fx_ver.cpp
index 254f408effe9b8..7a857cdff473b0 100644
--- a/src/native/corehost/fxr/fx_ver.cpp
+++ b/src/native/corehost/fxr/fx_ver.cpp
@@ -70,31 +70,18 @@ bool fx_ver_t::operator >=(const fx_ver_t& b) const
pal::string_t fx_ver_t::as_str() const
{
- pal::stringstream_t stream;
- stream << m_major << _X(".") << m_minor << _X(".") << m_patch;
+ pal::string_t version = pal::to_string(m_major);
+ version += _X('.');
+ version += pal::to_string(m_minor);
+ version += _X('.');
+ version += pal::to_string(m_patch);
if (!m_pre.empty())
- {
- stream << m_pre;
- }
- if (!m_build.empty())
- {
- stream << m_build;
- }
- return stream.str();
-}
+ version += m_pre;
-pal::string_t fx_ver_t::prerelease_glob() const
-{
- pal::stringstream_t stream;
- stream << m_major << _X(".") << m_minor << _X(".") << m_patch << _X("-*");
- return stream.str();
-}
+ if (!m_build.empty())
+ version += m_build;
-pal::string_t fx_ver_t::patch_glob() const
-{
- pal::stringstream_t stream;
- stream << m_major << _X(".") << m_minor << _X(".*");
- return stream.str();
+ return version;
}
static pal::string_t getId(const pal::string_t &ids, size_t idStart)
diff --git a/src/native/corehost/fxr/fx_ver.h b/src/native/corehost/fxr/fx_ver.h
index 5f5348386897b0..29f010876e04ae 100644
--- a/src/native/corehost/fxr/fx_ver.h
+++ b/src/native/corehost/fxr/fx_ver.h
@@ -26,8 +26,6 @@ struct fx_ver_t
bool is_empty() const { return m_major == -1; }
pal::string_t as_str() const;
- pal::string_t prerelease_glob() const;
- pal::string_t patch_glob() const;
bool operator ==(const fx_ver_t& b) const;
bool operator !=(const fx_ver_t& b) const;
diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp
index 46ffaf951adfb9..34520aefd7365a 100644
--- a/src/native/corehost/hostmisc/pal.unix.cpp
+++ b/src/native/corehost/hostmisc/pal.unix.cpp
@@ -16,7 +16,6 @@
#include
#include
#include
-#include
#include
#include "config.h"
#include
diff --git a/src/native/corehost/hostmisc/pal.windows.cpp b/src/native/corehost/hostmisc/pal.windows.cpp
index 98e4efbed72f07..b11610492d3214 100644
--- a/src/native/corehost/hostmisc/pal.windows.cpp
+++ b/src/native/corehost/hostmisc/pal.windows.cpp
@@ -7,7 +7,6 @@
#include "longfile.h"
#include
-#include
#include
#include
diff --git a/src/native/corehost/hostpolicy/version.cpp b/src/native/corehost/hostpolicy/version.cpp
index ea643605ac88f2..c08316fe4b5a87 100644
--- a/src/native/corehost/hostpolicy/version.cpp
+++ b/src/native/corehost/hostpolicy/version.cpp
@@ -51,29 +51,31 @@ bool version_t::operator >=(const version_t& b) const
pal::string_t version_t::as_str() const
{
- pal::stringstream_t stream;
-
+ pal::string_t version;
if (m_major >= 0)
{
- stream << m_major;
+ version += pal::to_string(m_major);
if (m_minor >= 0)
{
- stream << _X(".") << m_minor;
+ version += _X('.');
+ version += pal::to_string(m_minor);
if (m_build >= 0)
{
- stream << _X(".") << m_build;
+ version += _X('.');
+ version += pal::to_string(m_build);
if (m_revision >= 0)
{
- stream << _X(".") << m_revision;
+ version += _X('.');
+ version += pal::to_string(m_revision);
}
}
}
}
- return stream.str();
+ return version;
}
/*static*/ int version_t::compare(const version_t&a, const version_t& b)
From 702d02c87b1601a6ec5f6cd6fa008bc9bb1b8adc Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 15:58:58 -0700
Subject: [PATCH 037/345] [release/8.0-rc1] Improve filtering of candidate
binding invocations in config binder gen (#90746)
* Improve filtering of candidate binding invocations in config binder gen
* Address feedback
* Address feedback: rename helper; further tighten constraint
* Add follow-up TODO
* Revert TypeSyntax clause to fix failing tests
---------
Co-authored-by: Layomi Akinrinade
---
.../ConfigurationBindingGenerator.Parser.cs | 10 +---
.../gen/ConfigurationBindingGenerator.cs | 8 +--
.../gen/Helpers/Parser/BinderInvocation.cs | 59 ++++++++-----------
3 files changed, 31 insertions(+), 46 deletions(-)
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs
index 758311958c4515..b0f53ef074078f 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs
@@ -7,7 +7,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.Operations;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
@@ -44,13 +43,10 @@ public Parser(SourceProductionContext context, KnownTypeSymbols typeSymbols, Imm
foreach (BinderInvocation invocation in _invocations)
{
- IInvocationOperation invocationOperation = invocation.Operation!;
- if (!invocationOperation.TargetMethod.IsExtensionMethod)
- {
- continue;
- }
+ IMethodSymbol targetMethod = invocation.Operation.TargetMethod;
+ INamedTypeSymbol? candidateBinderType = targetMethod.ContainingType;
+ Debug.Assert(targetMethod.IsExtensionMethod);
- INamedTypeSymbol? candidateBinderType = invocationOperation.TargetMethod.ContainingType;
if (SymbolEqualityComparer.Default.Equals(candidateBinderType, _typeSymbols.ConfigurationBinder))
{
RegisterMethodInvocation_ConfigurationBinder(invocation);
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs
index 5d7a830c729542..70da582dddf0cd 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs
@@ -31,11 +31,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
? new CompilationData((CSharpCompilation)compilation)
: null);
- IncrementalValuesProvider inputCalls = context.SyntaxProvider
+ IncrementalValuesProvider inputCalls = context.SyntaxProvider
.CreateSyntaxProvider(
- (node, _) => node is InvocationExpressionSyntax invocation,
+ (node, _) => BinderInvocation.IsCandidateSyntaxNode(node),
BinderInvocation.Create)
- .Where(operation => operation is not null);
+ .Where(invocation => invocation is not null);
IncrementalValueProvider<(CompilationData?, ImmutableArray)> inputData = compilationData.Combine(inputCalls.Collect());
@@ -59,7 +59,7 @@ private static void Execute(CompilationData compilationData, ImmutableArray
IsCandidateMethodName_ConfigurationBinder(name) ||
@@ -52,23 +40,24 @@ static bool IsCandidateBindingMethodName(string name) =>
IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(name);
}
- private static bool IsCandidateInvocation(IInvocationOperation operation)
+ private static bool IsBindingOperation(IInvocationOperation operation)
{
if (operation.TargetMethod is not IMethodSymbol
{
IsExtensionMethod: true,
Name: string methodName,
- ContainingType: ITypeSymbol
+ ContainingType: INamedTypeSymbol
{
Name: string containingTypeName,
- ContainingNamespace: INamespaceSymbol { } containingNamespace,
- } containingType
- } method ||
- containingNamespace.ToDisplayString() is not string containingNamespaceName)
+ ContainingNamespace: INamespaceSymbol containingNamespace,
+ }
+ })
{
return false;
}
+ string containingNamespaceName = containingNamespace.ToDisplayString();
+
return (containingTypeName) switch
{
"ConfigurationBinder" =>
From 149a289ddcdb0bb319e50ccf05010f02efc97049 Mon Sep 17 00:00:00 2001
From: mikelle-rogers <45022607+mikelle-rogers@users.noreply.github.com>
Date: Thu, 17 Aug 2023 16:00:36 -0700
Subject: [PATCH 038/345] Revert "Put HasNativeCodeReJITAware into
GetFunctionAddress (#90049)" (#90696)
This reverts commit eacb32e400b3f9d3522bed193bd534d02e8b170a.
Need to investigate changes because they caused a test failure.
---
src/coreclr/debug/daccess/dacimpl.h | 11 ++++++
src/coreclr/debug/daccess/task.cpp | 4 +-
src/coreclr/debug/di/breakpoint.cpp | 2 -
src/coreclr/debug/ee/controller.cpp | 24 ++++++++++--
src/coreclr/debug/ee/debugger.cpp | 56 +++++++++++++++++++++------
src/coreclr/debug/ee/debugger.h | 4 +-
src/coreclr/debug/ee/functioninfo.cpp | 12 +++++-
src/coreclr/debug/inc/dbgipcevents.h | 1 -
src/coreclr/vm/dbginterface.h | 7 +++-
src/coreclr/vm/eedbginterfaceimpl.cpp | 1 +
src/coreclr/vm/encee.cpp | 4 +-
src/coreclr/vm/method.cpp | 19 ++++-----
src/coreclr/vm/method.hpp | 8 ++--
13 files changed, 113 insertions(+), 40 deletions(-)
diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h
index 8de684a5dae9a2..ddf61370f416e9 100644
--- a/src/coreclr/debug/daccess/dacimpl.h
+++ b/src/coreclr/debug/daccess/dacimpl.h
@@ -1253,6 +1253,17 @@ class ClrDataAccess
/* [out] */ union STUB_BUF* outBuffer,
/* [out] */ ULONG32* outFlags);
+ DebuggerJitInfo* GetDebuggerJitInfo(MethodDesc* methodDesc,
+ TADDR addr)
+ {
+ if (g_pDebugger)
+ {
+ return g_pDebugger->GetJitInfo(methodDesc, (PBYTE)addr, NULL);
+ }
+
+ return NULL;
+ }
+
HRESULT GetMethodExtents(MethodDesc* methodDesc,
METH_EXTENTS** extents);
HRESULT GetMethodVarInfo(MethodDesc* methodDesc,
diff --git a/src/coreclr/debug/daccess/task.cpp b/src/coreclr/debug/daccess/task.cpp
index ddbf251b7b9825..9e428e81adef2b 100644
--- a/src/coreclr/debug/daccess/task.cpp
+++ b/src/coreclr/debug/daccess/task.cpp
@@ -5225,7 +5225,7 @@ EnumMethodInstances::Next(ClrDataAccess* dac,
}
}
- if (!m_methodIter.Current()->HasNativeCodeAnyVersion())
+ if (!m_methodIter.Current()->HasNativeCodeReJITAware())
{
goto NextMethod;
}
@@ -5243,7 +5243,7 @@ EnumMethodInstances::CdStart(MethodDesc* methodDesc,
CLRDATA_ENUM* handle)
{
if (!methodDesc->HasClassOrMethodInstantiation() &&
- !(methodDesc->HasNativeCodeAnyVersion()))
+ !methodDesc->HasNativeCodeReJITAware())
{
*handle = 0;
return S_FALSE;
diff --git a/src/coreclr/debug/di/breakpoint.cpp b/src/coreclr/debug/di/breakpoint.cpp
index 568d7fc9fc66ad..ad45df5c618ace 100644
--- a/src/coreclr/debug/di/breakpoint.cpp
+++ b/src/coreclr/debug/di/breakpoint.cpp
@@ -211,13 +211,11 @@ HRESULT CordbFunctionBreakpoint::Activate(BOOL fActivate)
if (codeIsIL)
{
pEvent->BreakpointData.nativeCodeMethodDescToken = pEvent->BreakpointData.nativeCodeMethodDescToken.NullPtr();
- pEvent->BreakpointData.codeStartAddress = 0;
}
else
{
pEvent->BreakpointData.nativeCodeMethodDescToken =
(m_code.GetValue()->AsNativeCode())->GetVMNativeCodeMethodDescToken().ToLsPtr();
- pEvent->BreakpointData.codeStartAddress = (m_code.GetValue()->AsNativeCode())->GetAddress();
}
// Note: we're sending a two-way event, so it blocks here
diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp
index 58e63ab399db2c..7dd186b4113d44 100644
--- a/src/coreclr/debug/ee/controller.cpp
+++ b/src/coreclr/debug/ee/controller.cpp
@@ -1247,8 +1247,26 @@ bool DebuggerController::BindPatch(DebuggerControllerPatch *patch,
startAddr = (CORDB_ADDRESS_TYPE *) CORDB_ADDRESS_TO_PTR(patch->GetDJI()->m_addrOfCode);
_ASSERTE(startAddr != NULL);
}
- //We should never be calling this function with both a NULL startAddr and a DJI that doesn't have code.
- _ASSERTE(startAddr != NULL);
+ if (startAddr == NULL)
+ {
+ // Should not be trying to place patches on MethodDecs's for stubs.
+ // These stubs will never get jitted.
+ CONSISTENCY_CHECK_MSGF(!pMD->IsWrapperStub(), ("Can't place patch at stub md %p, %s::%s",
+ pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName));
+
+ startAddr = (CORDB_ADDRESS_TYPE *)g_pEEInterface->GetFunctionAddress(pMD);
+ //
+ // Code is not available yet to patch. The prestub should
+ // notify us when it is executed.
+ //
+ if (startAddr == NULL)
+ {
+ LOG((LF_CORDB, LL_INFO10000,
+ "DC::BP: Patch at 0x%zx not bindable yet.\n", patch->offset));
+
+ return false;
+ }
+ }
}
_ASSERTE(!g_pEEInterface->IsStub((const BYTE *)startAddr));
@@ -8638,7 +8656,7 @@ bool DebuggerFuncEvalComplete::SendEvent(Thread *thread, bool fIpChanged)
// DebuggerEnCBreakpoint constructor - creates and activates a new EnC breakpoint
//
// Arguments:
-// offset - IL offset in the function to place the patch
+// offset - native offset in the function to place the patch
// jitInfo - identifies the function in which the breakpoint is being placed
// fTriggerType - breakpoint type: either REMAP_PENDING or REMAP_COMPLETE
// pAppDomain - the breakpoint applies to the specified AppDomain only
diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp
index d58a987244a8ea..a44a9e235f36cd 100644
--- a/src/coreclr/debug/ee/debugger.cpp
+++ b/src/coreclr/debug/ee/debugger.cpp
@@ -2841,8 +2841,6 @@ HRESULT Debugger::GetILToNativeMapping(PCODE pNativeCodeStartAddress, ULONG32 cM
}
CONTRACTL_END;
- _ASSERTE(pNativeCodeStartAddress != NULL);
-
#ifdef PROFILING_SUPPORTED
// At this point, we're pulling in the debugger.
if (!HasLazyData())
@@ -3009,7 +3007,6 @@ HRESULT Debugger::GetILToNativeMappingIntoArrays(
_ASSERTE(pcMap != NULL);
_ASSERTE(prguiILOffset != NULL);
_ASSERTE(prguiNativeOffset != NULL);
- _ASSERTE(pNativeCodeStartAddress != NULL);
// Any caller of GetILToNativeMappingIntoArrays had better call
// InitializeLazyDataIfNecessary first!
@@ -5414,6 +5411,28 @@ void Debugger::ReleaseAllRuntimeThreads(AppDomain *pAppDomain)
g_pEEInterface->ResumeFromDebug(pAppDomain);
}
+// Given a method, get's its EnC version number. 1 if the method is not EnCed.
+// Note that MethodDescs are reused between versions so this will give us
+// the most recent EnC number.
+int Debugger::GetMethodEncNumber(MethodDesc * pMethod)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ DebuggerJitInfo * dji = GetLatestJitInfoFromMethodDesc(pMethod);
+ if (dji == NULL)
+ {
+ // If there's no DJI, couldn't have been EnCed.
+ return 1;
+ }
+ return (int) dji->m_encVersion;
+}
+
+
bool Debugger::IsJMCMethod(Module* pModule, mdMethodDef tkMethod)
{
CONTRACTL
@@ -6200,6 +6219,25 @@ void Debugger::LockAndSendEnCRemapCompleteEvent(MethodDesc *pMD)
Thread *thread = g_pEEInterface->GetThread();
// Note that the debugger lock is reentrant, so we may or may not hold it already.
SENDIPCEVENT_BEGIN(this, thread);
+
+ EX_TRY
+ {
+ // Ensure the DJI for the latest version of this method has been pre-created.
+ // It's not clear whether this is necessary or not, but it shouldn't hurt since
+ // we're going to need to create it anyway since we'll be debugging inside it.
+ DebuggerJitInfo *dji = g_pDebugger->GetLatestJitInfoFromMethodDesc(pMD);
+ (void)dji; //prevent "unused variable" error from GCC
+ _ASSERTE( dji != NULL );
+ }
+ EX_CATCH
+ {
+ // GetLatestJitInfo could throw on OOM, but the debugger isn't resiliant to OOM.
+ // I'm not aware of any other legitimate reason why it may throw, so we'll ASSERT
+ // if it fails.
+ _ASSERTE(!"Unexpected exception from Debugger::GetLatestJitInfoFromMethodDesc on EnC remap complete");
+ }
+ EX_END_CATCH(RethrowTerminalExceptions);
+
// Send an EnC remap complete event to the Right Side.
DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
InitIPCEvent(ipce,
@@ -7827,7 +7865,6 @@ void Debugger::FirstChanceManagedExceptionCatcherFound(Thread *pThread,
// Implements DebugInterface
// Call by EE/exception. Must be on managed thread
_ASSERTE(GetThreadNULLOk() != NULL);
- _ASSERTE(pMethodAddr != NULL);
// Quick check.
if (!CORDebuggerAttached())
@@ -10461,7 +10498,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
DebuggerJitInfo * pDJI = NULL;
if ((pMethodDesc != NULL) && (pDMI != NULL))
{
- pDJI = pDMI->FindOrCreateInitAndAddJitInfo(pMethodDesc, PINSTRToPCODE(dac_cast(pEvent->BreakpointData.codeStartAddress)));
+ pDJI = pDMI->FindOrCreateInitAndAddJitInfo(pMethodDesc, NULL /* startAddr */);
}
{
@@ -12588,7 +12625,7 @@ DWORD Debugger::GetThreadIdHelper(Thread *pThread)
// does not own the memory provided via vars outparameter.
//-----------------------------------------------------------------------------
void Debugger::GetVarInfo(MethodDesc * fd, // [IN] method of interest
- CORDB_ADDRESS nativeCodeAddress, // [IN] which edit version
+ void *DebuggerVersionToken, // [IN] which edit version
SIZE_T * cVars, // [OUT] size of 'vars'
const ICorDebugInfo::NativeVarInfo **vars // [OUT] map telling where local vars are stored
)
@@ -12600,7 +12637,7 @@ void Debugger::GetVarInfo(MethodDesc * fd, // [IN] method of interest
}
CONTRACTL_END;
- DebuggerJitInfo * ji = g_pDebugger->GetJitInfo(fd, (const BYTE *)nativeCodeAddress);
+ DebuggerJitInfo * ji = (DebuggerJitInfo *)DebuggerVersionToken;
// If we didn't supply a DJI, then we're asking for the most recent version.
if (ji == NULL)
@@ -12924,11 +12961,6 @@ HRESULT Debugger::UpdateFunction(MethodDesc* pMD, SIZE_T encVersion)
// For each offset in the IL->Native map, set a new EnC breakpoint on the
// ones that we know could be remap points.
-
- // Depending on which DJI was picked, the code might compute different IL offsets. The JIT may not guarantee it produces
- // the same set of sequence points for every generic instantiation.
- // Inside ENCSequencePointHelper there is logic that skips IL offsets that map to the same native offset.
- // Its possible that one version of the code maps two IL offsets to the same native offset but another version of the code maps them to different offsets.
PTR_DebuggerILToNativeMap seqMap = pJitInfo->GetSequenceMap();
for (unsigned int i = 0; i < pJitInfo->GetSequenceMapCount(); i++)
{
diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h
index 2c2440ddaf6977..26edd26a96140b 100644
--- a/src/coreclr/debug/ee/debugger.h
+++ b/src/coreclr/debug/ee/debugger.h
@@ -1933,6 +1933,8 @@ class Debugger : public DebugInterface
bool IsJMCMethod(Module* pModule, mdMethodDef tkMethod);
+ int GetMethodEncNumber(MethodDesc * pMethod);
+
bool FirstChanceManagedException(Thread *pThread, SIZE_T currentIP, SIZE_T currentSP);
@@ -1978,7 +1980,7 @@ class Debugger : public DebugInterface
#endif // EnC_SUPPORTED
void GetVarInfo(MethodDesc * fd, // [IN] method of interest
- CORDB_ADDRESS nativeCodeAddress, // [IN] which edit version
+ void *DebuggerVersionToken, // [IN] which edit version
SIZE_T * cVars, // [OUT] size of 'vars'
const ICorDebugInfo::NativeVarInfo **vars // [OUT] map telling where local vars are stored
);
diff --git a/src/coreclr/debug/ee/functioninfo.cpp b/src/coreclr/debug/ee/functioninfo.cpp
index 19910c6429a9c6..76d4be3ab232f2 100644
--- a/src/coreclr/debug/ee/functioninfo.cpp
+++ b/src/coreclr/debug/ee/functioninfo.cpp
@@ -1565,7 +1565,9 @@ DebuggerJitInfo *DebuggerMethodInfo::FindOrCreateInitAndAddJitInfo(MethodDesc* f
GC_NOTRIGGER;
}
CONTRACTL_END;
+
_ASSERTE(fd != NULL);
+
// The debugger doesn't track Lightweight-codegen methods b/c they have no metadata.
if (fd->IsDynamicMethod())
{
@@ -1574,8 +1576,16 @@ DebuggerJitInfo *DebuggerMethodInfo::FindOrCreateInitAndAddJitInfo(MethodDesc* f
if (startAddr == NULL)
{
+ // This will grab the start address for the current code version.
startAddr = g_pEEInterface->GetFunctionAddress(fd);
- _ASSERTE(startAddr != NULL);
+ if (startAddr == NULL)
+ {
+ startAddr = fd->GetNativeCodeReJITAware();
+ if (startAddr == NULL)
+ {
+ return NULL;
+ }
+ }
}
else
{
diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h
index e9643e50f480a2..9fe1afd31a54ba 100644
--- a/src/coreclr/debug/inc/dbgipcevents.h
+++ b/src/coreclr/debug/inc/dbgipcevents.h
@@ -2011,7 +2011,6 @@ struct MSLAYOUT DebuggerIPCEvent
SIZE_T offset;
SIZE_T encVersion;
LSPTR_METHODDESC nativeCodeMethodDescToken; // points to the MethodDesc if !isIL
- CORDB_ADDRESS codeStartAddress;
} BreakpointData;
struct MSLAYOUT
diff --git a/src/coreclr/vm/dbginterface.h b/src/coreclr/vm/dbginterface.h
index 85b9785bccbb9b..daa57d25c86cf3 100644
--- a/src/coreclr/vm/dbginterface.h
+++ b/src/coreclr/vm/dbginterface.h
@@ -203,7 +203,7 @@ class DebugInterface
// Get debugger variable information for a specific version of a method
virtual void GetVarInfo(MethodDesc * fd, // [IN] method of interest
- CORDB_ADDRESS nativeCodeAddress, // [IN] which edit version
+ void *DebuggerVersionToken, // [IN] which edit version
SIZE_T * cVars, // [OUT] size of 'vars'
const ICorDebugInfo::NativeVarInfo **vars // [OUT] map telling where local vars are stored
) = 0;
@@ -262,6 +262,11 @@ class DebugInterface
virtual bool IsJMCMethod(Module* pModule, mdMethodDef tkMethod) = 0;
+ // Given a method, get's its EnC version number. 1 if the method is not EnCed.
+ // Note that MethodDescs are reused between versions so this will give us
+ // the most recent EnC number.
+ virtual int GetMethodEncNumber(MethodDesc * pMethod) = 0;
+
virtual void SendLogSwitchSetting (int iLevel,
int iReason,
_In_z_ LPCWSTR pLogSwitchName,
diff --git a/src/coreclr/vm/eedbginterfaceimpl.cpp b/src/coreclr/vm/eedbginterfaceimpl.cpp
index 352a534d5c1a88..792c608918a61d 100644
--- a/src/coreclr/vm/eedbginterfaceimpl.cpp
+++ b/src/coreclr/vm/eedbginterfaceimpl.cpp
@@ -630,6 +630,7 @@ PCODE EEDbgInterfaceImpl::GetFunctionAddress(MethodDesc *pFD)
SUPPORTS_DAC;
}
CONTRACTL_END;
+
return pFD->GetNativeCode();
}
diff --git a/src/coreclr/vm/encee.cpp b/src/coreclr/vm/encee.cpp
index 3339462ad7fe77..1dcfb8bf091f4c 100644
--- a/src/coreclr/vm/encee.cpp
+++ b/src/coreclr/vm/encee.cpp
@@ -806,8 +806,8 @@ NOINLINE void EditAndContinueModule::FixContextAndResume(
// Get the var info which the codemanager will use for updating
// enregistered variables correctly, or variables whose lifetimes differ
// at the update point
- g_pDebugInterface->GetVarInfo(pMD, oldCodeInfo.GetCodeAddress(), &oldVarInfoCount, &pOldVarInfo);
- g_pDebugInterface->GetVarInfo(pMD, newCodeInfo.GetCodeAddress(), &newVarInfoCount, &pNewVarInfo);
+ g_pDebugInterface->GetVarInfo(pMD, oldDebuggerFuncHandle, &oldVarInfoCount, &pOldVarInfo);
+ g_pDebugInterface->GetVarInfo(pMD, NULL, &newVarInfoCount, &pNewVarInfo);
#ifdef TARGET_X86
// save the frame pointer as FixContextForEnC might step on it.
diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp
index 29910d6cb4c1c3..62b24e3dc091c6 100644
--- a/src/coreclr/vm/method.cpp
+++ b/src/coreclr/vm/method.cpp
@@ -913,6 +913,7 @@ PCODE MethodDesc::GetNativeCode()
WRAPPER_NO_CONTRACT;
SUPPORTS_DAC;
_ASSERTE(!IsDefaultInterfaceMethod() || HasNativeCodeSlot());
+
if (HasNativeCodeSlot())
{
// When profiler is enabled, profiler may ask to rejit a code even though we
@@ -934,7 +935,7 @@ PCODE MethodDesc::GetNativeCode()
return GetStableEntryPoint();
}
-PCODE MethodDesc::GetNativeCodeAnyVersion()
+PCODE MethodDesc::GetNativeCodeReJITAware()
{
WRAPPER_NO_CONTRACT;
SUPPORTS_DAC;
@@ -945,23 +946,19 @@ PCODE MethodDesc::GetNativeCodeAnyVersion()
return pDefaultCode;
}
- else
{
CodeVersionManager *pCodeVersionManager = GetCodeVersionManager();
CodeVersionManager::LockHolder codeVersioningLockHolder;
- ILCodeVersionCollection ilVersionCollection = pCodeVersionManager->GetILCodeVersions(PTR_MethodDesc(this));
- for (ILCodeVersionIterator curIL = ilVersionCollection.Begin(), endIL = ilVersionCollection.End(); curIL != endIL; curIL++)
+ ILCodeVersion ilVersion = pCodeVersionManager->GetActiveILCodeVersion(PTR_MethodDesc(this));
+ if (!ilVersion.IsDefaultVersion())
{
- NativeCodeVersionCollection nativeCollection = curIL->GetNativeCodeVersions(PTR_MethodDesc(this));
- for (NativeCodeVersionIterator curNative = nativeCollection.Begin(), endNative = nativeCollection.End(); curNative != endNative; curNative++)
+ NativeCodeVersion activeNativeCodeVersion = ilVersion.GetActiveNativeCodeVersion(PTR_MethodDesc(this));
+ if (!activeNativeCodeVersion.IsNull())
{
- PCODE native = curNative->GetNativeCode();
- if(native != NULL)
- {
- return native;
- }
+ return activeNativeCodeVersion.GetNativeCode();
}
}
+
return NULL;
}
}
diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp
index aaecfb20779f34..4b34045b57671e 100644
--- a/src/coreclr/vm/method.hpp
+++ b/src/coreclr/vm/method.hpp
@@ -1373,11 +1373,11 @@ class MethodDesc
}
// Perf warning: takes the CodeVersionManagerLock on every call
- BOOL HasNativeCodeAnyVersion()
+ BOOL HasNativeCodeReJITAware()
{
LIMITED_METHOD_DAC_CONTRACT;
- return GetNativeCodeAnyVersion() != NULL;
+ return GetNativeCodeReJITAware() != NULL;
}
BOOL SetNativeCodeInterlocked(PCODE addr, PCODE pExpected = NULL);
@@ -1437,9 +1437,9 @@ class MethodDesc
PCODE GetNativeCode();
// Returns GetNativeCode() if it exists, but also checks to see if there
- // is a non-default code version that is populated with a code body and returns that.
+ // is a non-default IL code version and returns that.
// Perf warning: takes the CodeVersionManagerLock on every call
- PCODE GetNativeCodeAnyVersion();
+ PCODE GetNativeCodeReJITAware();
#if defined(FEATURE_JIT_PITCHING)
bool IsPitchable();
From f7df78f4c9b3944d1b937b264601d7b5da55f3ab Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 17 Aug 2023 16:02:08 -0700
Subject: [PATCH 039/345] [release/8.0] Limit language version on Logger and
Options source gens (#90709)
* Limit language version on Logger and Options source gens
* Exclude test in browser
* Address the feedback
* Fix Json test and apply more feedback
* Remove quotes from language versions in source gen diagnostics. (#90720)
---------
Co-authored-by: Tarek Mahmoud Sayed
Co-authored-by: Eirik Tsarpalis
---
docs/project/list-of-diagnostics.md | 10 +--
.../gen/DiagnosticDescriptors.cs | 8 +++
.../gen/LoggerMessageGenerator.Parser.cs | 7 ++
.../gen/Resources/Strings.resx | 6 ++
.../gen/Resources/xlf/Strings.cs.xlf | 10 +++
.../gen/Resources/xlf/Strings.de.xlf | 10 +++
.../gen/Resources/xlf/Strings.es.xlf | 10 +++
.../gen/Resources/xlf/Strings.fr.xlf | 10 +++
.../gen/Resources/xlf/Strings.it.xlf | 10 +++
.../gen/Resources/xlf/Strings.ja.xlf | 10 +++
.../gen/Resources/xlf/Strings.ko.xlf | 10 +++
.../gen/Resources/xlf/Strings.pl.xlf | 10 +++
.../gen/Resources/xlf/Strings.pt-BR.xlf | 10 +++
.../gen/Resources/xlf/Strings.ru.xlf | 10 +++
.../gen/Resources/xlf/Strings.tr.xlf | 10 +++
.../gen/Resources/xlf/Strings.zh-Hans.xlf | 10 +++
.../gen/Resources/xlf/Strings.zh-Hant.xlf | 10 +++
.../LoggerMessageGeneratorParserTests.cs | 54 +++++++++++++-
.../gen/DiagDescriptors.cs | 7 ++
.../gen/Parser.cs | 7 ++
.../gen/Resources/Strings.resx | 6 ++
.../gen/Resources/xlf/Strings.cs.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.de.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.es.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.fr.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.it.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.ja.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.ko.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.pl.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.pt-BR.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.ru.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.tr.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.zh-Hans.xlf | 70 +++++++++++--------
.../gen/Resources/xlf/Strings.zh-Hant.xlf | 70 +++++++++++--------
.../tests/SourceGeneration.Unit.Tests/Main.cs | 57 +++++++++++++++
.../Resources/Strings.resx | 6 ++
.../Resources/Strings.resx | 6 ++
.../gen/Resources/Strings.resx | 56 +++++++--------
.../gen/Resources/xlf/Strings.cs.xlf | 4 +-
.../gen/Resources/xlf/Strings.de.xlf | 4 +-
.../gen/Resources/xlf/Strings.es.xlf | 4 +-
.../gen/Resources/xlf/Strings.fr.xlf | 4 +-
.../gen/Resources/xlf/Strings.it.xlf | 4 +-
.../gen/Resources/xlf/Strings.ja.xlf | 4 +-
.../gen/Resources/xlf/Strings.ko.xlf | 4 +-
.../gen/Resources/xlf/Strings.pl.xlf | 4 +-
.../gen/Resources/xlf/Strings.pt-BR.xlf | 4 +-
.../gen/Resources/xlf/Strings.ru.xlf | 4 +-
.../gen/Resources/xlf/Strings.tr.xlf | 4 +-
.../gen/Resources/xlf/Strings.zh-Hans.xlf | 4 +-
.../gen/Resources/xlf/Strings.zh-Hant.xlf | 4 +-
.../JsonSourceGeneratorDiagnosticsTests.cs | 8 +--
52 files changed, 876 insertions(+), 454 deletions(-)
diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md
index 4f78e9e711653d..75d252218f8392 100644
--- a/docs/project/list-of-diagnostics.md
+++ b/docs/project/list-of-diagnostics.md
@@ -142,10 +142,10 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| __`SYSLIB1023`__ | Generating more than 6 arguments is not supported |
| __`SYSLIB1024`__ | Argument is using the unsupported out parameter modifier |
| __`SYSLIB1025`__ | Multiple logging methods cannot use the same event name within a class |
-| __`SYSLIB1026`__ | _`SYSLIB1026`-`SYSLIB1029` reserved for logging._ |
-| __`SYSLIB1027`__ | _`SYSLIB1026`-`SYSLIB1029` reserved for logging._ |
-| __`SYSLIB1028`__ | _`SYSLIB1026`-`SYSLIB1029` reserved for logging._ |
-| __`SYSLIB1029`__ | _`SYSLIB1026`-`SYSLIB1029` reserved for logging._ |
+| __`SYSLIB1026`__ | C# language version not supported by the logging source generator. |
+| __`SYSLIB1027`__ | _`SYSLIB1001`-`SYSLIB1029` reserved for logging._ |
+| __`SYSLIB1028`__ | _`SYSLIB1001`-`SYSLIB1029` reserved for logging._ |
+| __`SYSLIB1029`__ | _`SYSLIB1001`-`SYSLIB1029` reserved for logging._ |
| __`SYSLIB1030`__ | JsonSourceGenerator did not generate serialization metadata for type |
| __`SYSLIB1031`__ | JsonSourceGenerator encountered a duplicate JsonTypeInfo property name |
| __`SYSLIB1032`__ | JsonSourceGenerator encountered a context class that is not partial |
@@ -250,7 +250,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| __`SYSLIB1213`__ | Options validation generator: Member potentially missing enumerable validation. |
| __`SYSLIB1214`__ | Options validation generator: Can't validate constants, static fields or properties. |
| __`SYSLIB1215`__ | Options validation generator: Validation attribute on the member is inaccessible from the validator type. |
-| __`SYSLIB1216`__ | *_`SYSLIB1201`-`SYSLIB1219` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
+| __`SYSLIB1216`__ | C# language version not supported by the options validation source generator. |
| __`SYSLIB1217`__ | *_`SYSLIB1201`-`SYSLIB1219` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
| __`SYSLIB1218`__ | *_`SYSLIB1201`-`SYSLIB1219` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
| __`SYSLIB1219`__ | *_`SYSLIB1201`-`SYSLIB1219` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs
index ed51ed6164188d..ec89ae4a42bc9a 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs
@@ -200,5 +200,13 @@ public static class DiagnosticDescriptors
category: "LoggingGenerator",
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
+
+ public static DiagnosticDescriptor LoggingUnsupportedLanguageVersion { get; } = new DiagnosticDescriptor(
+ id: "SYSLIB1026",
+ title: new LocalizableResourceString(nameof(SR.LoggingUnsupportedLanguageVersionTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ messageFormat: new LocalizableResourceString(nameof(SR.LoggingUnsupportedLanguageVersionMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+ category: "LoggingGenerator",
+ defaultSeverity: DiagnosticSeverity.Error,
+ isEnabledByDefault: true);
}
}
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
index 2b5b8ca6a1a498..038b71bef0759b 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
@@ -591,6 +591,13 @@ static bool IsAllowedKind(SyntaxKind kind) =>
}
}
+ if (results.Count > 0 && _compilation is CSharpCompilation { LanguageVersion : LanguageVersion version and < LanguageVersion.CSharp8 })
+ {
+ // we only support C# 8.0 and above
+ Diag(DiagnosticDescriptors.LoggingUnsupportedLanguageVersion, null, version.ToDisplayString(), LanguageVersion.CSharp8.ToDisplayString());
+ return Array.Empty();
+ }
+
return results;
}
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx
index 529263fda731fb..602e6f4730d216 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx
@@ -231,4 +231,10 @@
Logging method contains malformed format strings
+
+ C# language version not supported by the source generator.
+
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
\ No newline at end of file
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf
index ac5ddc07ceb05f..00e8b1cc7d91a1 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf
@@ -67,6 +67,16 @@
Metody protokolování musí být statické.
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsMetoda protokolování {0} obsahuje řetězce s poškozeným formátem.
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf
index c57008e516a5be..2e962cd97ac902 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf
@@ -67,6 +67,16 @@
Protokollierungsmethoden müssen statisch sein.
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsDie Protokollierungsmethode „{0}“ enthält nicht wohlgeformte Formatzeichenfolgen.
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf
index 29cce5c24f3f77..46073f102868a1 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf
@@ -67,6 +67,16 @@
Los métodos de registro deben ser estáticos
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsEl método de registro “{0}” contiene cadenas con formato incorrecto
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf
index afd2c184fc42fa..2497ea11a88a04 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf
@@ -67,6 +67,16 @@
Les méthodes de journalisation doivent être statiques
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsLa méthode de journalisation « {0} »contient des chaînes de format incorrectes
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf
index 99b2e817511ae8..06dadffd497939 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf
@@ -67,6 +67,16 @@
I metodi di registrazione devono essere statici
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsIl metodo di registrazione '{0}' contiene stringhe in formato non valido
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf
index a8c79393a42f23..bd03905bfba997 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf
@@ -67,6 +67,16 @@
ログ メソッドは静的である必要があります
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsログ メソッド '{0}' に、形式の正しくない文字列が含まれています
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf
index 0b77d9c65adb5f..eea8ef2203ac1d 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf
@@ -67,6 +67,16 @@
로깅 메서드는 정적이어야 함
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format strings로깅 메서드 '{0}'에 잘못된 형식의 문자열이 포함되어 있습니다.
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf
index 2784dfa601576b..6dbecb86f7fc43 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf
@@ -67,6 +67,16 @@
Metody rejestrowania muszą być statyczne
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsMetoda rejestrowania „{0}” zawiera źle sformułowane ciągi formatu
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf
index 22b9fabb3b2965..f7de3a39c5a055 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf
@@ -67,6 +67,16 @@
Os métodos de registro em log devem ser estáticos
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsO método de registro '{0}' contém strings de formato malformado
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf
index 4446666caf4828..9599e0f6b9b809 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf
@@ -67,6 +67,16 @@
Методы ведения журнала должны быть статическими
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format stringsМетод ведения журнала событий "{0}" содержит строки неправильного формата
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf
index fb21d7e0bd62ed..529a109ef75304 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf
@@ -67,6 +67,16 @@
Günlüğe kaydetme yöntemleri statik olmalıdır
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format strings'{0}' günlüğe kaydetme yöntemi hatalı biçimlendirilmiş biçim dizeleri içeriyor
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf
index 021f321ddf4b9f..879c6a773643a1 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf
@@ -67,6 +67,16 @@
日志记录方法必须为静态方法
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format strings日志记录方法“{0}”包含格式错误的字符串
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf
index c50c7054e6ee2a..42061caa455c27 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf
@@ -67,6 +67,16 @@
記錄方法必須是靜態
+
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+ The Logging source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.
+
+ Logging method '{0}' contains malformed format strings記錄方法 '{0}' 包含格式錯誤的格式字串
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs
index 462111ad00c372..dc677e81cfc4a0 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs
@@ -4,10 +4,12 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
using SourceGenerators.Tests;
using Xunit;
@@ -108,7 +110,7 @@ partial class C
{{
[LoggerMessage({argumentList})]
static partial void M1(ILogger logger, string foo);
-
+
[LoggerMessage({argumentList})]
static partial void M2(ILogger logger, LogLevel level, string foo);
}}
@@ -911,6 +913,56 @@ static partial void M1(ILogger logger)
Assert.Equal(DiagnosticDescriptors.LoggingMethodHasBody.Id, diagnostics[0].Id);
}
+ [Fact]
+ public async Task LanguageVersionTest()
+ {
+ string source = """
+ using Microsoft.Extensions.Logging;
+
+ internal partial class Program
+ {
+ static void Main() { }
+
+ [LoggerMessage(
+ EventId = 0,
+ Level = LogLevel.Critical,
+ Message = "Could not open socket to `{hostName}`")]
+ static partial void CouldNotOpenSocket(ILogger logger, string hostName);
+ }
+ """;
+
+ Assembly[]? refs = new[] { typeof(ILogger).Assembly, typeof(LoggerMessageAttribute).Assembly };
+
+ // Run the generator with C# 7.0 and verify that it fails.
+ var (diagnostics, generatedSources) = await RoslynTestUtils.RunGenerator(
+ new LoggerMessageGenerator(), refs, new[] { source }, includeBaseReferences: true, LanguageVersion.CSharp7).ConfigureAwait(false);
+
+ Assert.NotEmpty(diagnostics);
+ Assert.Equal("SYSLIB1026", diagnostics[0].Id);
+ Assert.Empty(generatedSources);
+
+ // Run the generator with C# 8.0 and verify that it succeeds.
+ (diagnostics, generatedSources) = await RoslynTestUtils.RunGenerator(
+ new LoggerMessageGenerator(), refs, new[] { source }, includeBaseReferences: true, LanguageVersion.CSharp8).ConfigureAwait(false);
+
+ Assert.Empty(diagnostics);
+ Assert.Single(generatedSources);
+
+ // Compile the generated code with C# 7.0 and verify that it fails.
+ CSharpParseOptions parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7);
+ SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(generatedSources[0].SourceText.ToString(), parseOptions);
+ var diags = syntaxTree.GetDiagnostics().ToArray();
+ Assert.Equal(1, diags.Length);
+ // error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater.
+ Assert.Equal("CS8107", diags[0].Id);
+
+ // Compile the generated code with C# 8.0 and verify that it succeeds.
+ parseOptions = new CSharpParseOptions(LanguageVersion.CSharp8);
+ syntaxTree = SyntaxFactory.ParseSyntaxTree(generatedSources[0].SourceText.ToString(), parseOptions);
+ diags = syntaxTree.GetDiagnostics().ToArray();
+ Assert.Equal(0, diags.Length);
+ }
+
private static async Task> RunGenerator(
string code,
bool wrap = true,
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs b/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs
index 474686189fb126..141fc6b9c7f9ae 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs
+++ b/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs
@@ -105,5 +105,12 @@ internal sealed class DiagDescriptors : DiagDescriptorsBase
messageFormat: SR.InaccessibleValidationAttributeMessage,
category: Category,
defaultSeverity: DiagnosticSeverity.Info);
+
+ public static DiagnosticDescriptor OptionsUnsupportedLanguageVersion { get; } = Make(
+ id: "SYSLIB1216",
+ title: SR.OptionsUnsupportedLanguageVersionTitle,
+ messageFormat: SR.OptionsUnsupportedLanguageVersionMessage,
+ category: Category,
+ defaultSeverity: DiagnosticSeverity.Error);
}
}
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs
index 07ea7de51bf9a4..0c8e216e488c7f 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs
@@ -143,6 +143,13 @@ public IReadOnlyList GetValidatorTypes(IEnumerable<(TypeDeclarati
results.AddRange(_synthesizedValidators.Values);
_synthesizedValidators.Clear();
+ if (results.Count > 0 && _compilation is CSharpCompilation { LanguageVersion : LanguageVersion version and < LanguageVersion.CSharp8 })
+ {
+ // we only support C# 8.0 and above
+ Diag(DiagDescriptors.OptionsUnsupportedLanguageVersion, null, version.ToDisplayString(), LanguageVersion.CSharp8.ToDisplayString());
+ return new List();
+ }
+
return results;
}
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx
index ef074f147f915e..6293431eb7f90e 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx
@@ -207,4 +207,10 @@
Validation attribute on the member is inaccessible from the validator type..
+
+ C# language version not supported by the source generator.
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf
index fadfdec9e3b7ad..7054599d224576 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- Typ {0} již implementuje metodu Validate.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Typ už obsahuje implementaci metody Validate.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator] nelze použít pro statickou třídu {0}.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- OptionsValidatorAttribute nelze použít pro statickou třídu.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- U polí nebo vlastností s otevřeným obecným typem {0} nelze použít [ValidateObjectMembers] nebo [ValidateEnumeratedItems].
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- U polí nebo vlastností s otevřenými obecnými typy nelze použít ValidateObjectMembersAttribute nebo ValidateEnumeratedItemsAttribute.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Atributy ověřování nelze použít u konstantního ani statického člena {0}.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Nelze ověřit konstanty, statická pole ani vlastnosti.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Existuje cyklický odkaz obsahující typ {0}, který brání jeho použití pro statické ověření.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Nepodporované cyklické odkazy v typech modelů.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- Typ {0} neimplementuje požadované rozhraní IValidateOptions<{1}> .
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Typ anotovaný třídou OptionsValidatorAttribute neimplementuje nezbytné rozhraní.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- Ověřovací atribut „{0}“ u člena „{1}“ není přístupný z typu validátoru „{2}“.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- Ověřovací atribut u člena není přístupný z typu validátoru.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Ověřovací atributy nelze použít u privátního pole nebo vlastnosti {0}.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Nelze ověřit privátní pole nebo vlastnosti.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- Typ {0} nemá žádná pole ani vlastnosti k ověření, na které odkazuje člen {1}.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Typ člena nemá žádná pole ani vlastnosti k ověření.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- Typ {0} nemá žádná pole ani vlastnosti k ověření, na které odkazuje typ {1}.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Typ nemá žádná pole ani vlastnosti k ověření.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] nelze použít u členů typu {0}, protože neimplementuje rozhraní IEnumerable<T>.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- Typ členu není výčtový.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- Typ validátoru s hodnotou null zadaný v atributech [ValidateObjectMembers] nebo [ValidateEnumeratedItems].
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Pro atributy ValidateObjectMembersAttribute nebo ValidateEnumeratedItemsAttribute byl specifikovaný typ validátoru s hodnotou null.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- Typ {0} obsahuje validační anotace, ale člen {1} neurčuje [ValidateEnumeratedItems], což může být přehlédnutí.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- U člena potenciálně chybí ověření výčtu.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- Typ {0} obsahuje validační anotace, ale člen {1} neurčuje [ValidateObjectMembers], což může být přehlédnutí.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- U člena potenciálně chybí přenositelné ověření.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- Typ validátoru {0} nemá konstruktor bez parametrů.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- Validátory používané pro přenositelné nebo výčtové ověřování musí mít konstruktor bez parametrů.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.de.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.de.xlf
index badb9618ac043b..5f6febba85c205 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.de.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.de.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- Der Typ "{0}" implementiert bereits die Validate-Methode.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Ein Typ enthält bereits eine Implementierung der Validate-Methode.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator] kann nicht auf die statische Klasse "{0}" angewendet werden.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- "OptionsValidatorAttribute" kann nicht auf eine statische Klasse angewendet werden.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- "ValidateObjectMembers" oder "ValidateEnumeratedItems" kann nicht für Felder oder Eigenschaften mit offenem generischen Typ {0} verwendet werden.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- "ValidateObjectMembersAttribute" oder "ValidateEnumeratedItemsAttribute" kann nicht für Felder oder Eigenschaften mit offenen generischen Typen verwendet werden.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Validierungsattribute können nicht auf konstanten oder statischen Member {0} angewendet werden.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Konstanten, statische Felder oder Eigenschaften können nicht überprüft werden.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Es gibt einen Zirkelverweis, der den Typ "{0}" verhindert, dass er für die statische Validierung verwendet wird.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Nicht unterstützte Zirkelverweise in Modelltypen.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- Der Typ "{0}" implementiert nicht die erforderliche IValidateOptions<{1}>-Schnittstelle.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Ein mit "OptionsValidatorAttribute" versehener Typ implementiert nicht die erforderliche Schnittstelle.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- Auf das Validierungsattribut "{0}" für den Member "{1}" kann vom Validierungssteuerelementtyp "{2}" nicht zugegriffen werden.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- Auf das Validierungsattribut für den Member kann vom Validierungssteuerelementtyp nicht zugegriffen werden.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Validierungsattribute können nicht auf private Felder oder Eigenschaften {0} angewendet werden.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Private Felder oder Eigenschaften können nicht überprüft werden.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- Der Typ "{0}" weist keine zu überprüfenden Felder oder Eigenschaften auf, auf die von Member "{1}" verwiesen wird.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Ein Membertyp weist keine zu überprüfenden Felder oder Eigenschaften auf.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- Der Typ "{0}" weist keine zu überprüfenden Felder oder Eigenschaften auf, auf die vom Typ "{1}" verwiesen wird.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Ein Typ weist keine zu überprüfenden Felder oder Eigenschaften auf.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] kann nicht für Member vom Typ "{0}" verwendet werden, da es IEnumerable<T> nicht implementiert.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- Der Membertyp ist nicht aufzählbar.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- Der in den Attributen [ValidateObjectMembers] oder [ValidateEnumeratedItems] angegebene NULL-Validierungssteuerelementtyp.
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Für die Attribute "ValidateObjectMembersAttribute" oder "ValidateEnumeratedItemsAttribute" wurde ein NULL-Validierungssteuerelementtyp angegeben.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- Der Typ "{0}" weist Validierungsanmerkungen auf, der Member "{1}" gibt jedoch keine [ValidateEnumeratedItems] an, die eine Vorhersage darstellen könnten.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- Dem Mitglied fehlt möglicherweise eine aufzählbare Validierung.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- Der Typ "{0}" weist Validierungsanmerkungen auf, aber Member "{1}" gibt [ValidateObjectMembers] nicht an, was ein Versehen sein könnte.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- Dem Member fehlt möglicherweise die transitive Validierung.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- Der Validierungssteuerelementtyp "{0}" hat keinen parameterlosen Konstruktor.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- Validierungssteuerelemente, die für die transitive oder enumerierbare Validierung verwendet werden, müssen über einen Konstruktor ohne Parameter verfügen.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.es.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.es.xlf
index 9637c745a081e0..84c12b9739ab1a 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.es.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.es.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- El tipo {0} ya implementa el método Validate.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Un tipo ya incluye una implementación del método “Validate”.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- No se puede aplicar [OptionsValidator] a la clase estática {0}.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- “OptionsValidatorAttribute” no se puede aplicar a una clase estática.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- No se puede usar [ValidateObjectMembers] ni [ValidateEnumeratedItems] en campos o propiedades con tipos genéricos abiertos {0}.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- No se puede usar “ValidateObjectMembersAttribute” o “ValidateEnumeratedItemsAttribute” en campos o propiedades con tipos genéricos abiertos.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- No se pueden aplicar atributos de validación a un miembro {0}constante o estático.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- No se pueden validar constantes, campos estáticos ni propiedades.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Hay una referencia de tipo circular que implica al tipo {0} que impide que se use para la validación estática.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Referencias circulares no admitidas en los tipos de modelo.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- El tipo {0} no implementa la interfaz IValidateOptions<{1}> necesaria.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Un tipo anotado con “OptionsValidatorAttribute” no implementa la interfaz necesaria.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- No se puede obtener acceso al atributo de validación '{0}' en el miembro '{1}' desde el tipo de validador '{2}'.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- No se puede obtener acceso al atributo de validación en el miembro desde el tipo de validador.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- No se pueden aplicar atributos de validación a la propiedad o campo privado {0}.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- No se pueden validar los campos o propiedades privadas.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- El tipo {0} no tiene campos ni propiedades para validar, al que hace referencia el tipo {1}.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Un tipo de miembro no tiene campos ni propiedades para validar.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- El tipo {0} no tiene campos ni propiedades para validar, al que hace referencia el tipo {1}.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Un tipo no tiene campos ni propiedades para validar.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] no se puede usar en miembros de tipo {0} porque no implementa IEnumerable<T>.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- El tipo de miembro no es enumerable.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- Se especificó un tipo de validador nulo en los atributos [ValidateObjectMembers] o [ValidateEnumeratedItems].
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Se especificó un tipo de validador nulo para los atributos “ValidateObjectMembersAttribute” o “ValidateEnumeratedItemsAttribute”.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- El tipo {0} tiene anotaciones de validación, pero el miembro {1} no especifica [ValidateEnumeratedItems], lo que podría ser un error.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- Posiblemente falta la validación enumerable en el miembro.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- El tipo {0} tiene anotaciones de validación, pero el miembro {1} no especifica [ValidateObjectMembers], lo que podría ser un error.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- Posiblemente falta la validación transitiva en el miembro.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- El tipo de validador {0} no tiene un constructor sin parámetros.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- Los validadores usados para la validación transitiva o enumerable deben tener un constructor sin parámetros.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.fr.xlf
index 93817f52c7ddf7..58a27f1e4b33cb 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.fr.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.fr.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- Le type {0} implémente déjà la méthode Validate.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Un type inclut déjà une implémentation de la méthode 'Validate'.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator] ne peut pas être appliqué à la classe statique {0}.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- 'OptionsValidatorAttribute' ne peut pas être appliqué à une classe statique.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- Impossible d’utiliser [ValidateObjectMembers] ou [ValidateEnumeratedItems] sur des champs ou des propriétés avec un type générique ouvert {0}.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- Impossible d’utiliser 'ValidateObjectMembersAttribute' ou 'ValidateEnumeratedItemsAttribute' sur des champs ou des propriétés avec des types génériques ouverts.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Impossible d’appliquer les attributs de validation au membre constant ou statique {0}.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Impossible de valider les constantes, les champs statiques ou les propriétés.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Une référence de type circulaire implique un type {0} l’empêche d’être utilisé pour la validation statique.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Références circulaires non prises en charge dans les types de modèle.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- Le type {0} n’implémente pas l’interface<{1}> IValidateOptions requise.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Un type annoté avec 'OptionsValidatorAttribute' n’implémente pas l’interface nécessaire.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- L’attribut de validation '{0}' sur le membre '{1}' n’est pas accessible à partir du type de validateur '{2}'.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- L’attribut de validation sur le membre n’est pas accessible à partir du type de validateur.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Impossible d’appliquer les attributs de validation au champ privé ou à la propriété {0}.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Impossible de valider les champs ou propriétés privés.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- Le type {0} n’a aucun champ ou propriété à valider, référencé à partir du membre {1}.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Un type de membre n’a aucun champ ou propriété à valider.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- Le type {0} n’a pas de champs ou de propriétés à valider, référencé par type {1}.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Un type n’a pas de champs ou de propriétés à valider.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] ne peut pas être utilisé sur des membres de type {0}, car il n’implémente pas IEnumerable<T>.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- Le type de membre n’est pas énumérable.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- Type de validateur Null spécifié dans les attributs [ValidateObjectMembers] ou [ValidateEnumeratedItems].
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Type de validateur Null spécifié pour les attributs 'ValidateObjectMembersAttribute' ou 'ValidateEnumeratedItemsAttribute'.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- Le type {0} a des annotations de validation, mais le membre {1} ne spécifie pas [ValidateEnumeratedItems] qui peut être une supervision.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- Le membre n’a peut-être pas de validation énumérable.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- Le type {0} a des annotations de validation, mais le membre {1} ne spécifie pas [ValidateObjectMembers] qui pourrait être une méthode de récupération.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- Le membre n’a peut-être pas de validation transitive.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- Le type de validateur {0} n’a pas de constructeur sans paramètre.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- Les validateurs utilisés pour la validation transitive ou énumérable doivent avoir un constructeur sans paramètres.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.it.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.it.xlf
index b80d8e27bcec22..2355a93c01db99 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.it.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.it.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- Il tipo {0} implementa già il metodo Validate.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Un tipo include già un'implementazione del metodo 'Validate'.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- impossibile applicare [OptionsValidator] alla classe statica {0}.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- 'OptionsValidatorAttribute' non può essere applicato a una classe statica.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- Non è possibile usare [ValidateObjectMembers] o [ValidateEnumeratedItems] in campi o proprietà con tipo generico aperto {0}.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- Non è possibile usare 'ValidateObjectMembersAttribute' o 'ValidateEnumeratedItemsAttribute' nei campi o nelle proprietà con tipi generici aperti.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Non è possibile applicare attributi di convalida a un membro costante o statico {0}.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Non è possibile convalidare costanti, campi statici o proprietà.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Esiste un riferimento di tipo circolare che interessa il tipo {0} e ne impedisce l'utilizzo per la convalida statica.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Riferimenti circolari non supportati nei tipi di modello.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- Il tipo {0} non implementa l'interfaccia IValidateOptions<{1}> richiesta.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Un tipo annotato con 'OptionsValidatorAttribute' non implementa l'interfaccia necessaria.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- L'attributo di convalida '{0}' nel membro '{1}' non è accessibile dal tipo di validator '{2}'.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- L'attributo di convalida nel membro non è accessibile dal tipo di validator.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Non è possibile applicare gli attributi di convalida al campo privato o alla proprietà {0}.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Non è possibile convalidare proprietà o campi privati.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- Il tipo {0} non contiene campi o proprietà da convalidare, riferiti dal membro {1}.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Un tipo di membro non contiene campi o proprietà da convalidare.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- Il tipo {0} non contiene campi o proprietà da convalidare, riferiti per tipo {1}.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Un tipo non contiene campi o proprietà da convalidare.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] non può essere usato nei membri di tipo {0} perché non implementa IEnumerable<T>.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- Il tipo di membro non è enumerabile.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- Tipo di validator Null specificato negli attributi [ValidateObjectMembers] o [ValidateEnumeratedItems].
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Tipo di validator Null specificato per gli attributi 'ValidateObjectMembersAttribute' o 'ValidateEnumeratedItemsAttribute'.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- Il tipo {0} include annotazioni di convalida, ma il membro {1} non specifica [ValidateEnumeratedItems] che potrebbe essere una supervisione.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- Convalida enumerabile potenzialmente mancante nel membro.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- Il tipo {0} include annotazioni di convalida, ma il membro {1} non specifica [ValidateObjectMembers] che potrebbe essere una supervisione.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- Il membro potrebbe non avere una convalida transitiva.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- Il tipo di convalida {0} non dispone di un costruttore senza parametri.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- I convalidatori usati per la convalida transitiva o enumerabile devono avere un costruttore senza parametri.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ja.xlf
index b9b44dd4afd5e5..60e9a7db80c8d4 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ja.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ja.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- 型 {0} に Validate メソッドが既に実装されています。
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- 型には 'Validate' メソッドの実装が既に含まれています。
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- 静的クラス {0} には [OptionsValidator] を適用できません。
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- 'OptionsValidatorAttribute' は静的クラスに適用できません。
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- [ValidateObjectMembers] または [ValidateEnumeratedItems] は、オープンジェネリック型 {0} を持つフィールドまたはプロパティでは使用できません。
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- 'ValidateObjectMembersAttribute' または 'ValidateEnumeratedItemsAttribute' は、オープンジェネリック型を持つフィールドまたはプロパティでは使用できません。
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- 定数または静的メンバー {0} に検証属性を適用できません。
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- 定数、静的フィールド、またはプロパティを検証できません。
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- 型{0}を含む循環型参照があるため、静的検証に使用できません。
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- モデル型でサポートされていない循環参照です。
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- 必要な IValidateOptions<{1}> インターフェイスが型 {0} に実装されていません。
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- 'OptionsValidatorAttribute' の注釈が付けられた型が、必要とされるインターフェイスを実装していません。
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- メンバー '{0}' の検証属性 '{1}' は、検証コントロールの種類 '{2}'からアクセスできません。
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- メンバーの検証属性は、検証コントロールの種類からアクセスできません...
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- プライベート フィールドまたはプロパティ {0} には検証属性を適用できません。
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- プライベート フィールドまたはプロパティを検証できません。
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- 型 {0} にメンバー {1} から参照されている検証対象のフィールドまたはプロパティがありません。
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- メンバー型に検証対象のフィールドまたはプロパティがありません。
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- 型 {0} に型 {1} で参照されている検証対象のフィールドまたはプロパティがありません。
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- 型に検証対象のフィールドまたはプロパティがありません。
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] は IEnumerable<T> を実装していないため、型 {0} のメンバーでは使用できません。
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- メンバー型は列挙型ではありません。
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- [ValidateObjectMembers] 属性または [ValidateEnumeratedItems] 属性で null のバリデーター型が指定されています。
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- 'ValidateObjectMembersAttribute' 属性または 'ValidateEnumeratedItemsAttribute' 属性に対して NULL のバリデーター型が指定されています。
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- 型 {0} には検証の注釈がありますが、メンバー {1} では [ValidateEnumeratedItem] が指定されていません。これは誤りである可能性があります。
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- 列挙型の検証がメンバーに存在しない可能性があります。
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- 型 {0} には検証の注釈がありますが、メンバー {1} では [ValidateObjectMembers] が指定されていません。これは誤りである可能性があります。
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- メンバーに推移性の検証がない可能性があります。
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- バリデーター型 {0} にパラメーターなしのコンストラクターがありません。
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- 推移性または列挙型の検証に使用されるバリデーターには、パラメーターのないコンストラクターが必要です。
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ko.xlf
index 45819c9f750a5a..e350b2f6f437de 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ko.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ko.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- 형식 {0}은(는) Validate 메서드를 이미 구현하고 있습니다.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- 형식에 'Validate' 메서드 구현이 이미 포함되어 있습니다.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator]은(는) 정적 클래스 {0}에 적용할 수 없습니다.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- 'OptionsValidatorAttribute'는 정적 클래스에 적용할 수 없습니다.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- 열린 제네릭 형식 {0}의 필드 또는 속성에는 [ValidateObjectMembers] 또는 [ValidateEnumeratedItems]을(를) 사용할 수 없습니다.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- 열린 제네릭 형식의 필드 또는 속성에는 'ValidateObjectMembersAttribute' 또는 'ValidateEnumeratedItemsAttribute'를 사용할 수 없습니다.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- 상수 또는 정적 멤버 {0}에 유효성 검사 특성을 적용할 수 없습니다.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- 상수, 정적 필드 또는 속성을 확인할 수 없습니다.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- 정적 유효성 검사에 사용할 수 없으므로 형식 {0} 관련된 순환 형식 참조가 있습니다.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- 모델 형식에 지원되지 않는 순환 참조가 있습니다.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- 형식 {0}은(는) 필요한 IValidateOptions<{1}> 인터페이스를 구현하지 않습니다.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- 'OptionsValidatorAttribute'로 주석이 추가된 형식은 필요한 인터페이스를 구현하지 않습니다.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- 유효성 검사기 유형 '{2}'에서 '{1}' 멤버의 '{0}' 유효성 검사 특성에 액세스할 수 없습니다.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- 유효성 검사기 유형에서 멤버의 유효성 검사 특성에 액세스할 수 없습니다.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- 프라이빗 필드 또는 속성 {0}에 유효성 검사 특성을 적용할 수 없습니다.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- 프라이빗 필드 또는 속성의 유효성을 검사할 수 없습니다.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- 형식 {0}은(는) 유효성을 검사할 필드 또는 속성이 없으므로 멤버 {1}을(를) 참조합니다.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- 멤버 형식에 유효성을 검사할 필드 또는 속성이 없습니다.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- 형식 {0}은(는) 유효성을 검사할 필드 또는 속성이 없으므로 형식 {1}을(를) 참조합니다.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- 형식에 유효성을 검사할 필드 또는 속성이 없습니다.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems]은(는) IEnumerable<T>을(를) 구현하지 않으므로 형식 {0}의 멤버에 사용할 수 없습니다.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- 멤버 형식을 열거할 수 없습니다.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- [ValidateObjectMembers] 또는 [ValidateEnumeratedItems] 특성에 Null 유효성 검사기 형식이 지정되었습니다.
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- 'ValidateObjectMembersAttribute' 또는 'ValidateEnumeratedItemsAttribute' 특성에 Null 유효성 검사기 형식이 지정되었습니다.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- 형식 {0}은(는) 유효성 검사 주석이 있지만 멤버 {1}은(는) 참조할 수 있는 [ValidateEnumeratedItems]을(를) 지정하지 않습니다.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- 멤버에 열거 가능한 유효성 검사가 누락되었을 수 있습니다.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- 형식 {0}은(는) 유효성 검사 주석이 있지만 멤버 {1}은(는) 참조할 수 있는 [ValidateObjectMembers]을(를) 지정하지 않습니다.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- 멤버에 전이적 유효성 검사가 누락되었을 수 있습니다.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- 유효성 검사기 형식 {0}은(는) 매개 변수가 없는 생성자가 없습니다.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- 전이적 또는 열거형 유효성 검사에 사용되는 유효성 검사기에는 매개 변수가 없는 생성자가 있어야 합니다.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pl.xlf
index 0b57a0ac378924..edaf8b9d00e9ba 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pl.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pl.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- Typ {0} już implementuje metodę Validate.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Typ zawiera już implementację metody „Validate”.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- Nie można zastosować elementu [OptionsValidator] do klasy statycznej {0}.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- Nie można zastosować elementu „OptionsValidatorAttribute” do klasy statycznej.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- Nie można użyć atrybutu [ValidateObjectMembers] lub [ValidateEnumeratedItems] w polach lub właściwościach z otwartymi typami ogólnymi {0}.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- Nie można użyć atrybutu „ValidateObjectMembersAttribute” lub „ValidateEnumeratedItemsAttribute” w polach lub właściwościach z otwartymi typami ogólnymi.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Nie można zastosować atrybutów walidacji do stałych lub statycznych elementów członkowskich {0}.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Nie można zweryfikować stałych, pól statycznych lub właściwości.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Istnieje cykliczne odwołanie do typu dotyczące typu {0} uniemożliwiające użycie go do weryfikacji statycznej.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Nieobsługiwane odwołania cykliczne w typach modeli.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- Typ {0} nie implementuje wymaganego interfejsu IValidateOptions<{1}>.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Typ z adnotacją „OptionsValidatorAttribute” nie implementuje wymaganego interfejsu.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- Atrybut walidacji „{0}” elementu członkowskiego „{1}” jest niedostępny z typu modułu sprawdzania poprawności „{2}”.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- Atrybut walidacji elementu członkowskiego jest niedostępny z typu modułu sprawdzania poprawności.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Nie można zastosować atrybutów weryfikacji do pola prywatnego lub właściwości {0}.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Nie można zweryfikować prywatnych pól lub właściwości.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- Typ {0} nie ma pól ani właściwości do zweryfikowania, do których odwołuje się element członkowski {1}.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Typ elementu członkowskiego nie ma pól ani właściwości do zweryfikowania.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- Typ {0} nie ma pól ani właściwości do zweryfikowania, do których odwołuje się typ {1}.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Typ nie ma pól ani właściwości do zweryfikowania.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- Atrybutu [ValidateEnumeratedItems] nie można używać w przypadku elementów członkowskich typu {0}, ponieważ nie implementuje interfejsu IEnumerable<T>.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- Nie można wyliczyć typu elementu członkowskiego.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- W atrybutach [ValidateObjectMembers] lub [ValidateEnumeratedItems] określono typ modułu sprawdzania poprawności o wartości null.
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Określono typ modułu sprawdzania poprawności o wartości null dla atrybutu „ValidateObjectMembersAttribute” lub „ValidateEnumeratedItemsAttribute”.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- Typ {0} ma adnotacje walidacji, ale element członkowski {1} nie określa atrybutu [ValidateEnumeratedItems], co może być przeoczeniem.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- W elemencie członkowskim może brakować walidacji możliwej do wyliczenia.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- Typ {0} ma adnotacje walidacji, ale element członkowski {1} nie określa atrybutu [ValidateObjectMembers], co może być przeoczeniem.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- W przypadku elementu członkowskiego może potencjalnie brakować weryfikacji przechodniej.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- Typ modułu sprawdzania poprawności {0} nie ma konstruktora bez parametrów.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- Moduły sprawdzania poprawności używane do weryfikacji przechodniej lub weryfikacji możliwej do wyliczenia muszą mieć konstruktora bez żadnych parametrów.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pt-BR.xlf
index 4afa1d6763db8b..f62a1ef241e372 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pt-BR.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pt-BR.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- O tipo {0} já implementa o método Validar.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Um tipo já inclui uma implementação do método "Validar".
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator] não pode ser aplicado à classe estática {0}.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- "OptionsValidatorAttribute" não pode ser aplicado a uma classe estática.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- Não é possível usar [ValidateObjectMembers] ou [ValidateEnumeratedItems] em campos ou propriedades com o tipo genérico aberto {0}.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- Não é possível usar "ValidateObjectMembersAttribute" ou "ValidateEnumeratedItemsAttribute" em campos ou propriedades com tipos genéricos abertos.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Não é possível aplicar atributos de validação a um membro constante ou estático {0}.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Não é possível validar constantes, campos estáticos ou propriedades.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Há uma referência de tipo circular que envolve o tipo {0} que a impede de ser usada para validação estática.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Referências circulares sem suporte em tipos de modelo.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- O tipo {0} não implementa a interface IValidateOptions<{1}> necessária.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Um tipo anotado com "OptionsValidatorAttribute" não implementa a interface necessária.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- O atributo de validação '{0}' no membro '{1}' está inacessível do tipo de validador '{2}'.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- O atributo de validação no membro está inacessível do tipo de validador.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Não é possível aplicar atributos de validação a um campo privado ou propriedade {0}.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Não é possível validar propriedades ou campos privados.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- O tipo {0} não tem campos ou propriedades para validar, referenciados do membro {1}.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Um tipo de membro não tem campos ou propriedades a serem validados.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- O tipo {0} não tem campos ou propriedades para validar, referenciados por tipo {1}.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Um tipo não tem campos ou propriedades a serem validados.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] não pode ser usado em membros do tipo {0}, pois ele não implementa IEnumerable<T>.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- O tipo de membro não é enumerável.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- Tipo de validador nulo especificado nos atributos [ValidateObjectMembers] ou [ValidateEnumeratedItems].
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Tipo de validador nulo especificado para os atributos "ValidateObjectMembersAttribute" ou "ValidateEnumeratedItemsAttribute".
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- O tipo {0} tem anotações de validação, mas o membro {1} não especifica [ValidateEnumeratedItems], o que pode ser uma desatenção.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- Membro potencialmente ausente na validação enumerável.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- O tipo {0} tem anotações de validação, mas o membro {1} não especifica [ValidateObjectMembers], o que pode ser uma desatenção.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- Membro potencialmente ausente na validação transitiva.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- O tipo de validador {0} não tem um construtor sem parâmetros.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- Os validadores usados para validação transitiva ou enumerável devem ter um construtor sem parâmetros.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ru.xlf
index 02fb57d5497df9..b8069e4266ae37 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ru.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ru.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- Тип {0} уже реализует метод Validate.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Тип уже содержит реализацию метода Validate.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator] невозможно применить к статическому классу {0}.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- Параметр OptionsValidatorAttribute не может быть применен к статическому классу.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- Нельзя использовать [ValidateObjectMembers] или [ValidateEnumeratedItems] для полей или свойств с открытыми универсальными типами {0}.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- Нельзя использовать "ValidateObjectMembersAttribute" или "ValidateEnumeratedItemsAttribute" для полей или свойств с открытыми универсальными типами.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Не удалось применить атрибуты проверки к константе или статическому элементу {0}.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Не удалось проверить константы, статические поля или свойства.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Существует циклическая ссылка на тип, включающая тип {0}, предотвращающий его использование для статической проверки.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Неподдерживаемые циклические ссылки в типах моделей.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- Тип {0} не реализует требуемый интерфейс IValidateOptions<{1}>.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- Тип с аннотацией OptionsValidatorAttribute не реализует необходимый интерфейс.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- Атрибут проверки "{0}" элемента "{1}" недоступен из типа средства проверки "{2}".
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- Атрибут проверки элемента недоступен из типа средства проверки.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Не удается применить атрибуты проверки к закрытому полю или свойству {0}.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Не удается проверить частные поля или свойства.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- Тип {0} не содержит полей или свойств для проверки, на которые ссылается из элемента {1}.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Тип элемента не имеет полей или свойств для проверки.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- Тип {0} не содержит полей или свойств для проверки, на которые ссылается тип {1}.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Тип не имеет полей или свойств для проверки.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] не может использоваться для элементов типа {0}, так как он не реализует IEnumerable<T>.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- Тип элемента не является перечисляемым.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- Тип проверяющего элемента управления, указанный в [ValidateObjectMembers] или [ValidateEnumeratedItems] атрибутах, имеет значение NULL.
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- Для атрибутов ValidateObjectMembersAttribute или ValidateEnumeratedItemsAttribute указан тип проверяющего элемента управления NULL.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- Тип {0} содержит примечания проверки, но элемент {1} не указывает [ValidateEnumeratedItems], который может быть задан.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- Элемент потенциально пропускает перечисляемую проверку.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- Тип {0} содержит примечания проверки, но элемент {1} не указывает [ValidateObjectMembers], который может быть задан.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- Возможно, в элементе отсутствует транзитивная проверка.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- Тип проверяющего элемента управления {0} не имеет конструктора без параметров.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- У проверяющих элементов управления, используемых для транзитивной или перечисляемой проверки, должен быть конструктор без параметров.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.tr.xlf
index 6743baba13c804..8cb34b9b6f900a 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.tr.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.tr.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- {0} türü Doğrulama yöntemini zaten uyguluyor.
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- Bir tür zaten 'Validate' yönteminin bir uygulamasını içeriyor.
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator], {0} statik sınıfına uygulanamıyor.
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- 'OptionsValidatorAttribute' statik sınıfa uygulanamaz.
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- {0} açık genel türündeki alanlarda veya özelliklerde [ValidateObjectMembers] veya [ValidateEnumeratedItems] kullanılamaz.
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- Açık genel türleri olan alanlarda veya özelliklerde 'ValidateObjectMembersAttribute' veya 'ValidateEnumeratedItemsAttribute' kullanılamaz.
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- Doğrulama öznitelikleri sabit veya statik üye {0} için geçerli değildir.
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- Sabitler, statik alanlar veya özellikler doğrulanamıyor.
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- Statik doğrulama için kullanılmasını engelleyen {0} türü içeren döngüsel bir tür başvurusu var.
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- Model türlerde döngüsel başvurular desteklenmiyor.
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- {0} türü gerekli IValidateOptions<{1}> arabirimini uygulamıyor.
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- 'OptionsValidatorAttribute' ile açıklama eklenmiş bir tür gerekli arabirimi uygulamıyor.
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- '{1}' adlı üye üzerindeki '{0}' doğrulama özniteliğine '{2}' doğrulayıcı türünden erişilemiyor.
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- Üye üzerindeki doğrulama özniteliğine doğrulayıcı türünden erişilemiyor.
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- Doğrulama öznitelikleri, {0} özel alanına veya özelliğine uygulanamıyor.
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- Özel alanlar veya özellikler doğrulanamıyor.
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- {0} türünde doğrulanacak alan veya özellik yok, {1} üyesinden başvurulur.
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- Üye türünde doğrulanacak alan veya özellik yok.
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- {0} türünde doğrulanacak alan veya özellik yok, {1} türü tarafından başvurulur.
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- Türde doğrulanacak alan veya özellik yok.
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems], IEnumerable<T> uygulamadığından {0} türündeki üyeler üzerinde kullanılamıyor.
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- Üye türü numaralandırılabilir değil.
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- [ValidateObjectMembers] veya [ValidateEnumeratedItems] özniteliklerinde null doğrulayıcı türü belirtildi.
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- 'ValidateObjectMembersAttribute' veya 'ValidateEnumeratedItemsAttribute' öznitelikleri için null doğrulayıcı türü belirtildi.
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- {0} türünde doğrulama ek açıklamaları var, ancak {1} üyesi gözden kaçmış olabilecek [ValidateEnumeratedItems] belirtmiyor.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- Üyede numaralandırılabilir doğrulama eksik olabilir.
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- {0} türünde doğrulama ek açıklamaları var, ancak {1} üyesi gözden kaçmış olabilecek [ValidateObjectMembers] belirtmiyor.
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- Üyede geçişli doğrulama eksik olabilir.
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- {0} doğrulayıcı türü parametresiz bir oluşturucuya sahip değil.
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- Geçişli veya numaralandırılabilir doğrulama için kullanılan doğrulayıcıların parametresi olmayan bir oluşturucusu olmalıdır.
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hans.xlf
index cd68a3a773332b..707dcb36c697b0 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hans.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- 类型 {0} 已实现 Validate 方法。
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- 类型已包含“Validate”方法的实现。
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator] 无法应用于静态类 {0}。
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- “OptionsValidatorAttribute”不能应用于静态类。
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- 不能对具有开放泛型类型 {0} 的字段或属性使用 [ValidateObjectMembers] 或 [ValidateEnumeratedItems]。
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- 不能对具有开放泛型类型的字段或属性使用 "ValidateObjectMembersAttribute" 或 "ValidateEnumeratedItemsAttribute"。
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- 无法将验证属性应用于常量或静态成员 {0}。
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- 无法验证常量、静态字段或属性。
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- 存在一个循环类型引用,其中涉及的类型 {0} 阻止将其用于静态验证。
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- 模型类型中不支持的循环引用。
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- 类型 {0} 未实现所需的 IValidateOptions<{1}> 接口。
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- 用 "OptionsValidatorAttribute" 批注的类型未实现必要的接口。
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- 无法从验证程序类型“{2}”访问成员“{1}”上的验证属性“{0}”。
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- 无法从验证程序类型访问成员上的验证属性。
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- 无法将验证属性应用于专用字段或属性 {0}。
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- 无法验证专用字段或属性。
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- 类型 {0} 没有要验证的字段或属性,从成员 {1} 中引用。
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- 成员类型没有要验证的字段或属性。
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- 类型 {0} 没有要验证的字段或属性,由类型 {1} 引用。
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- 类型没有要验证的字段或属性。
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- 无法对类型 {0} 的成员使用 [ValidateEnumeratedItems],因为它未实现 IEnumerable<T>。
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- 成员类型不可枚举。
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- [ValidateObjectMembers] 或 [ValidateEnumeratedItems] 属性中指定的 Null 验证程序类型。
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- 为“ValidateObjectMembersAttribute”或“ValidateEnumeratedItemsAttribute”属性指定的验证程序类型为 Null。
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- 类型 {0} 具有验证注释,但成员 {1} 未指定 [ValidateEnumeratedItems],这可能是一种监督。
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- 成员可能缺少可枚举验证。
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- 类型 {0} 具有验证注释,但成员 {1} 未指定 [ValidateObjectMembers],这可能是一种监督。
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- 成员可能缺少可传递验证。
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- 验证程序类型 {0} 没有无参数构造函数。
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- 用于可传递验证或可枚举验证的验证程序必须具有没有参数的构造函数。
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hant.xlf
index f21a748ed078e7..f8087186cb294b 100644
--- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hant.xlf
+++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hant.xlf
@@ -4,152 +4,162 @@
Type {0} already implements the Validate method.
- 類型 {0} 已實作 [驗證] 方法。
+ Type {0} already implements the Validate method.A type already includes an implementation of the 'Validate' method.
- 類型已經包含 [驗證] 方法的實作。
+ A type already includes an implementation of the 'Validate' method.[OptionsValidator] cannot be applied to static class {0}.
- [OptionsValidator] 無法套用至靜態類別 {0}。
+ [OptionsValidator] cannot be applied to static class {0}.'OptionsValidatorAttribute' can't be applied to a static class.
- 無法將 'OptionsValidatorAttribute' 套用至靜態類別。
+ 'OptionsValidatorAttribute' can't be applied to a static class.Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.
- 無法在有開放式泛型型別 {0} 的欄位或屬性上使用 [ValidateObjectMembers] 或 [ValidateEnumeratedItems]。
+ Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.
- 無法在有開放式泛型型別的欄位或屬性上使用 'ValidateObjectMembersAttribute' 或 'ValidateEnumeratedItemsAttribute'。
+ Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.Can't apply validation attributes to constant or static member {0}.
- 無法將驗證屬性套用至常數或靜態成員 {0}。
+ Can't apply validation attributes to constant or static member {0}.Can't validate constants, static fields or properties.
- 無法驗證常數、靜態欄位或屬性。
+ Can't validate constants, static fields or properties.There is a circular type reference involving type {0} preventing it from being used for static validation.
- 有涉及類型 {0} 的循環類型參考讓它無法用於靜態驗證。
+ There is a circular type reference involving type {0} preventing it from being used for static validation.Unsupported circular references in model types.
- 模型類型中不支援的循環參考。
+ Unsupported circular references in model types.Type {0} does not implement the required IValidateOptions<{1}> interface.
- 類型 {0} 未實作必要的 IValidateOptions<{1}> 介面。
+ Type {0} does not implement the required IValidateOptions<{1}> interface.A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.
- 以 'OptionsValidatorAttribute' 附註的類型未實作必要的介面。
+ A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.
- 無法從驗證程式類型 '{2}' 存取成員 '{1}' 上的驗證屬性 '{0}'。
+ Validation attribute '{0}' on the member '{1}' is inaccessible from the validator type '{2}'.Validation attribute on the member is inaccessible from the validator type..
- 無法從驗證程式類型存取成員上的驗證屬性。
+ Validation attribute on the member is inaccessible from the validator type..Can't apply validation attributes to private field or property {0}.
- 無法將驗證屬性套用至私用欄位或屬性 {0}。
+ Can't apply validation attributes to private field or property {0}.Can't validate private fields or properties.
- 無法驗證私人欄位或屬性。
+ Can't validate private fields or properties.Type {0} has no fields or properties to validate, referenced from member {1}.
- 參照會員 {1},類型 {0} 沒有欄位或屬性可供驗證。
+ Type {0} has no fields or properties to validate, referenced from member {1}.A member type has no fields or properties to validate.
- 成員類型沒有欄位或屬性可供驗證。
+ A member type has no fields or properties to validate.Type {0} has no fields or properties to validate, referenced by type {1}.
- 參照類型 {1},類型 {0} 沒有欄位或屬性可供驗證。
+ Type {0} has no fields or properties to validate, referenced by type {1}.A type has no fields or properties to validate.
- 類型沒有欄位或屬性可供驗證。
+ A type has no fields or properties to validate.[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.
- [ValidateEnumeratedItems] 無法用於類型 {0} 的成員,因為其未實作 IEnumerable<T>。
+ [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.Member type is not enumerable.
- 成員類型無法列舉。
+ Member type is not enumerable.Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.
- [ValidateObjectMembers] 或 [ValidateEnumeratedItems] 屬性中指定的 Null 驗證程式類型。
+ Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
- 為 'ValidateObjectMembersAttribute' 或 'ValidateEnumeratedItemsAttribute' 屬性指定的 Null 驗證程式類型。
+ Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.
+
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
+
+
+ C# language version not supported by the source generator.
+ C# language version not supported by the source generator.Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.
- 成員 {0} 具備驗證註釋,但成員 {1} 未指定 [ValidateObjectMembers] (可能為監督)。
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.Member potentially missing enumerable validation.
- 成員可能遺漏可列舉的驗證。
+ Member potentially missing enumerable validation.Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.
- 類型 {0} 具備驗證註釋,但成員 {1} 未指定 [ValidateObjectMembers] (可能為監督)。
+ Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.Member potentially missing transitive validation.
- 成員可能遺漏轉移的驗證。
+ Member potentially missing transitive validation.Validator type {0} doesn't have a parameterless constructor.
- 驗證程式類型 {0} 沒有無參數建構函式。
+ Validator type {0} doesn't have a parameterless constructor.Validators used for transitive or enumerable validation must have a constructor with no parameters.
- 用於轉移或可列舉驗證的驗證程式必須具備沒有參數的建構函式。
+ Validators used for transitive or enumerable validation must have a constructor with no parameters.
diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs
index b243ee50f361d9..f3e0513a885f22 100644
--- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs
+++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs
@@ -1582,6 +1582,63 @@ public partial class FirstValidator : IValidateOptions
Assert.Equal(DiagDescriptors.NotEnumerableType.Id, diagnostics[0].Id);
}
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task LanguageVersionTest()
+ {
+ string source = """
+ using System;
+ using System.ComponentModel.DataAnnotations;
+ using Microsoft.Extensions.Options;
+
+ public class FirstModel
+ {
+ [Required]
+ public string? P1 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class FirstModelValidator : IValidateOptions
+ {
+ }
+ """;
+
+ Assembly [] refAssemblies = new []
+ {
+ Assembly.GetAssembly(typeof(RequiredAttribute)),
+ Assembly.GetAssembly(typeof(OptionsValidatorAttribute)),
+ Assembly.GetAssembly(typeof(IValidateOptions)),
+ };
+
+ // Run the generator with C# 7.0 and verify that it fails.
+ var (diagnostics, generatedSources) = await RoslynTestUtils.RunGenerator(
+ new Generator(), refAssemblies.ToArray(), new[] { source }, includeBaseReferences: true, LanguageVersion.CSharp7).ConfigureAwait(false);
+
+ Assert.NotEmpty(diagnostics);
+ Assert.Equal("SYSLIB1216", diagnostics[0].Id);
+ Assert.Empty(generatedSources);
+
+ // Run the generator with C# 8.0 and verify that it succeeds.
+ (diagnostics, generatedSources) = await RoslynTestUtils.RunGenerator(
+ new Generator(), refAssemblies.ToArray(), new[] { source }, includeBaseReferences: true, LanguageVersion.CSharp8).ConfigureAwait(false);
+
+ Assert.Empty(diagnostics);
+ Assert.Single(generatedSources);
+
+ // Compile the generated code with C# 7.0 and verify that it fails.
+ CSharpParseOptions parseOptions = new CSharpParseOptions(LanguageVersion.CSharp7);
+ SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(generatedSources[0].SourceText.ToString(), parseOptions);
+ var diags = syntaxTree.GetDiagnostics().ToArray();
+ Assert.Equal(1, diags.Length);
+ // error CS8107: Feature 'nullable reference types' is not available in C# 7.0. Please use language version 8.0 or greater.
+ Assert.Equal("CS8107", diags[0].Id);
+
+ // Compile the generated code with C# 8.0 and verify that it succeeds.
+ parseOptions = new CSharpParseOptions(LanguageVersion.CSharp8);
+ syntaxTree = SyntaxFactory.ParseSyntaxTree(generatedSources[0].SourceText.ToString(), parseOptions);
+ diags = syntaxTree.GetDiagnostics().ToArray();
+ Assert.Equal(0, diags.Length);
+ }
+
private static CSharpCompilation CreateCompilationForOptionsSource(string assemblyName, string source, string? refAssemblyPath = null)
{
// Ensure the generated source compiles
diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Resources/Strings.resx
index c6d9021ea99672..6b8167e94b119a 100644
--- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Resources/Strings.resx
+++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Resources/Strings.resx
@@ -210,4 +210,10 @@
Validation attribute on the member is inaccessible from the validator type..
+
+ C# language version not supported by the source generator.
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
\ No newline at end of file
diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx
index c6d9021ea99672..6b8167e94b119a 100644
--- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx
+++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx
@@ -210,4 +210,10 @@
Validation attribute on the member is inaccessible from the validator type..
+
+ C# language version not supported by the source generator.
+
+
+ The options validation source generator is not available in C# {0}. Please use language version {1} or greater.
+
\ No newline at end of file
diff --git a/src/libraries/System.Text.Json/gen/Resources/Strings.resx b/src/libraries/System.Text.Json/gen/Resources/Strings.resx
index 85d64b685f023d..519cbffa3ec09a 100644
--- a/src/libraries/System.Text.Json/gen/Resources/Strings.resx
+++ b/src/libraries/System.Text.Json/gen/Resources/Strings.resx
@@ -1,17 +1,17 @@
-
@@ -193,7 +193,7 @@
C# language version not supported by the source generator.
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.Constructor annotated with JsonConstructorAttribute is inaccessible.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf
index cc88af350de1e5..41ce7674876442 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- Zdrojový generátor System.Text.Json není k dispozici v jazyce C#{0}. Použijte prosím jazykovou verzi {1} nebo vyšší.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ Zdrojový generátor System.Text.Json není k dispozici v jazyce C#{0}. Použijte prosím jazykovou verzi {1} nebo vyšší.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf
index d23d07843bb212..a0b49aa02c03f3 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- Der System.Text.Json-Quellgenerator ist in C# „{0}“ nicht verfügbar. Verwenden Sie die Sprachversion {1} oder höher.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ Der System.Text.Json-Quellgenerator ist in C# „{0}“ nicht verfügbar. Verwenden Sie die Sprachversion {1} oder höher.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf
index 989c5a8a02f263..bdd7876fa38cd3 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- El generador de origen System.Text.Json no está disponible en C# '{0}'. Use la versión de idioma {1} o superior.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ El generador de origen System.Text.Json no está disponible en C# '{0}'. Use la versión de idioma {1} o superior.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf
index 4e1998a8f6e376..4b93e17edd6eb6 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- Le générateur de source System.Text.Json n'est pas disponible en C# '{0}'. Veuillez utiliser la version linguistique {1} ou supérieure.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ Le générateur de source System.Text.Json n'est pas disponible en C# '{0}'. Veuillez utiliser la version linguistique {1} ou supérieure.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf
index 5cb68b207cab19..cb163ff94ec4f9 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- Il generatore di origine System.Text.Json non è disponibile in C# '{0}'. Usare la versione del linguaggio {1} o successiva.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ Il generatore di origine System.Text.Json non è disponibile in C# '{0}'. Usare la versione del linguaggio {1} o successiva.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf
index a25a901571f489..9e3366a8bf09a2 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- System.Text.Json ソース ジェネレーターは C# '{0}' では使用できません。言語バージョン {1} 以上を使用してください。
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ System.Text.Json ソース ジェネレーターは C# '{0}' では使用できません。言語バージョン {1} 以上を使用してください。
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf
index dec5ff53a5aa12..735e6d772f7c26 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- System.Text.Json 원본 생성기는 C# '{0}'에서 사용할 수 없습니다. {1} 이상의 언어 버전을 사용하세요.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ System.Text.Json 원본 생성기는 C# '{0}'에서 사용할 수 없습니다. {1} 이상의 언어 버전을 사용하세요.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf
index bb1a603dbaf458..8282fa16aa908b 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- Generator źródła System.Text.Json nie jest dostępny w języku C# „{0}”. Użyj wersji językowej lub nowszej {1} .
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ Generator źródła System.Text.Json nie jest dostępny w języku C# „{0}”. Użyj wersji językowej lub nowszej {1} .
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf
index a4cb21e691b5dd..030a3f3302e729 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- O gerador de fonte System.Text.Json não está disponível em C# '{0}'. Use a versão do idioma {1} ou superior.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ O gerador de fonte System.Text.Json não está disponível em C# '{0}'. Use a versão do idioma {1} ou superior.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf
index d1c3241bc43f22..556fa665267f30 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- Генератор исходного кода System.Text.Json не доступен в C# "{0}". Используйте языковую версию {1} или выше.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ Генератор исходного кода System.Text.Json не доступен в C# "{0}". Используйте языковую версию {1} или выше.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf
index 72b706fdc31a64..e74d8818167e3d 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- System.Text.Json kaynak oluşturucusu C# '{0}' içinde kullanılamıyor. Lütfen dil sürümü {1} veya üstü sürümü kullanın.
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ System.Text.Json kaynak oluşturucusu C# '{0}' içinde kullanılamıyor. Lütfen dil sürümü {1} veya üstü sürümü kullanın.
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf
index 3450d312816e01..3ac4929b2b76dd 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- System.Text.Json 源生成器在 C#“{0}”中不可用。请使用{1}或更高版本的语言版本。
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ System.Text.Json 源生成器在 C#“{0}”中不可用。请使用{1}或更高版本的语言版本。
diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf
index 176989f5fc53a6..a194d8afc278d7 100644
--- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf
+++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf
@@ -113,8 +113,8 @@
- The System.Text.Json source generator is not available in C# '{0}'. Please use language version {1} or greater.
- C# '{0}' 中無法使用 System.Text.Json 來源產生器。請使用 {1} 或更新的語言版本。
+ The System.Text.Json source generator is not available in C# {0}. Please use language version {1} or greater.
+ C# '{0}' 中無法使用 System.Text.Json 來源產生器。請使用 {1} 或更新的語言版本。
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs
index 98f2b71042332b..a554d2681d43d1 100644
--- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs
+++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs
@@ -416,7 +416,7 @@ public void SupportedLanguageVersions_SucceedCompilation(LanguageVersion langVer
using System.Text.Json.Serialization;
namespace HelloWorld
- {
+ {
public class MyClass
{
public MyClass(int value)
@@ -457,7 +457,7 @@ public void SupportedLanguageVersions_Memory_SucceedCompilation(LanguageVersion
using System.Text.Json.Serialization;
namespace HelloWorld
- {
+ {
public class MyClass
{
public MyClass(
@@ -504,7 +504,7 @@ public void UnsupportedLanguageVersions_FailCompilation(LanguageVersion langVers
using System.Text.Json.Serialization;
namespace HelloWorld
- {
+ {
public class MyClass
{
public MyClass(int value)
@@ -531,7 +531,7 @@ public partial class MyJsonContext : JsonSerializerContext
var expectedDiagnostics = new DiagnosticData[]
{
- new(DiagnosticSeverity.Error, contextLocation, $"The System.Text.Json source generator is not available in C# '{langVersion.ToDisplayString()}'. Please use language version 9.0 or greater.")
+ new(DiagnosticSeverity.Error, contextLocation, $"The System.Text.Json source generator is not available in C# {langVersion.ToDisplayString()}. Please use language version 9.0 or greater.")
};
CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics);
From 52f3d10d7938e8748a43b25f69a4e6795e72822c Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 18 Aug 2023 11:11:07 -0700
Subject: [PATCH 040/345] Make DacValidateMD and DacValidateMethodTable more
resilient (#90797)
Make both methods more resilient to the case of invalid MethodDesc
and MethodTable with value -1.
Close #90691
Co-authored-by: Jan Vorlicek
---
src/coreclr/debug/daccess/request.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp
index 868593fae4651e..114900ffaf0365 100644
--- a/src/coreclr/debug/daccess/request.cpp
+++ b/src/coreclr/debug/daccess/request.cpp
@@ -135,11 +135,17 @@ BOOL DacValidateEEClass(PTR_EEClass pEEClass)
BOOL DacValidateMethodTable(PTR_MethodTable pMT, BOOL &bIsFree)
{
+ bIsFree = FALSE;
+
+ if ((pMT == NULL) || dac_cast(pMT) == (TADDR)-1)
+ {
+ return FALSE;
+ }
+
// Verify things are right.
BOOL retval = FALSE;
EX_TRY
{
- bIsFree = FALSE;
if (HOST_CDADDR(pMT) == HOST_CDADDR(g_pFreeObjectMethodTable))
{
bIsFree = TRUE;
@@ -182,7 +188,7 @@ BadMethodTable: ;
BOOL DacValidateMD(PTR_MethodDesc pMD)
{
- if (pMD == NULL)
+ if ((pMD == NULL) || dac_cast(pMD) == (TADDR)-1)
{
return FALSE;
}
From 20d508bf9597c73a063eec535bcb2fd5cabc7837 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 18 Aug 2023 12:50:30 -0700
Subject: [PATCH 041/345] [release/8.0-rc1] [wasm] Do not build mono libs with
`-msimd128` (#90750)
* [wasm] Do not build mono libs with `-msimd128`
Make it optional, build only minimal set of code witch required
`-msimd128` to separate library. Also provide "stub" nosimd
version of this library.
Choose the appropriate library during linking.
* Fix build
* Fix build of non-wasm platforms
* Add simd options for wasi
* Fix wasi build
---------
Co-authored-by: Radek Doulik
Co-authored-by: Larry Ewing
---
.../Directory.Build.props | 2 ++
src/mono/CMakeLists.txt | 8 -----
src/mono/mono.proj | 6 ++++
src/mono/mono/mini/CMakeLists.txt | 25 +++++++++++++--
src/mono/mono/mini/interp/interp-nosimd.c | 31 +++++++++++++++++++
src/mono/mono/mini/interp/interp-simd.c | 2 ++
src/mono/mono/mini/interp/interp-simd.h | 2 ++
src/mono/mono/mini/interp/transform-simd.c | 4 +++
src/mono/wasi/build/WasiApp.Native.targets | 6 ++++
src/mono/wasi/runtime/CMakeLists.txt | 1 +
src/mono/wasi/wasi.proj | 2 ++
src/mono/wasm/build/WasmApp.Native.targets | 6 ++++
src/mono/wasm/runtime/CMakeLists.txt | 1 +
src/mono/wasm/wasm.proj | 3 +-
14 files changed, 88 insertions(+), 11 deletions(-)
create mode 100644 src/mono/mono/mini/interp/interp-nosimd.c
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
index 13cf1fc895c8ac..5a96f57519aaf8 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
@@ -197,6 +197,8 @@
+
+
diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt
index 66e92d80564363..a57cc52b0b110b 100644
--- a/src/mono/CMakeLists.txt
+++ b/src/mono/CMakeLists.txt
@@ -242,14 +242,6 @@ elseif(CLR_CMAKE_HOST_OS STREQUAL "emscripten")
add_compile_options(-Wno-strict-prototypes)
add_compile_options(-Wno-unused-but-set-variable)
add_compile_options(-Wno-single-bit-bitfield-constant-conversion)
- # Allow using WASM simd intrinsics in the interpreter
- add_compile_options(-msimd128)
- # Disable autovectorization (it is automatically turned on by msimd128)
- add_compile_options(-disable-loop-vectorization)
- add_compile_options(-disable-vectorization)
- add_compile_options(-fno-vectorize)
- add_compile_options(-fno-tree-vectorize)
- add_compile_options(-fno-slp-vectorize)
set(DISABLE_EXECUTABLES 1)
# FIXME: Is there a cmake option for this ?
set(DISABLE_SHARED_LIBS 1)
diff --git a/src/mono/mono.proj b/src/mono/mono.proj
index cf99f325ea5565..6be683f8e2eb2c 100644
--- a/src/mono/mono.proj
+++ b/src/mono/mono.proj
@@ -1061,6 +1061,12 @@
<_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true' and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-wasm-eh-wasm.a">
$(RuntimeBinDir)libmono-wasm-eh-wasm.a
+ <_MonoRuntimeArtifacts Condition="('$(TargetsBrowser)' == 'true' or '$(TargetsWasi)' == 'true') and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-wasm-simd.a">
+ $(RuntimeBinDir)libmono-wasm-simd.a
+
+ <_MonoRuntimeArtifacts Condition="('$(TargetsBrowser)' == 'true' or '$(TargetsWasi)' == 'true') and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-wasm-nosimd.a">
+ $(RuntimeBinDir)libmono-wasm-nosimd.a
+
<_MonoICorDebugArtifacts Condition="'$(MonoMsCorDbi)' == 'true'" Include="$(MonoObjDir)out\lib\$(LibPrefix)mscordbi$(LibSuffix)">
$(RuntimeBinDir)$(LibPrefix)mscordbi$(LibSuffix)
diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt
index 884b43c1b1eec4..5d6ef3dfa3c31e 100644
--- a/src/mono/mono/mini/CMakeLists.txt
+++ b/src/mono/mono/mini/CMakeLists.txt
@@ -288,7 +288,6 @@ set(interp_sources
interp/interp.h
interp/interp-internals.h
interp/interp.c
- interp/interp-simd.c
interp/interp-intrins.h
interp/interp-intrins.c
interp/mintops.h
@@ -297,11 +296,17 @@ set(interp_sources
interp/tiering.h
interp/tiering.c
interp/jiterpreter.c)
+set(interp_simd_sources
+ interp/interp-simd.c)
set(interp_stub_sources
interp-stubs.c)
if(NOT DISABLE_INTERPRETER)
-set(mini_interp_sources ${interp_sources})
+ if(HOST_WASM)
+ set(mini_interp_sources ${interp_sources})
+ else()
+ set(mini_interp_sources ${interp_sources} ${interp_simd_sources})
+ endif()
else()
set(mini_interp_sources ${interp_stub_sources})
endif()
@@ -504,6 +509,19 @@ if(HOST_BROWSER)
install(TARGETS mono-wasm-eh-wasm LIBRARY)
endif()
+if(HOST_BROWSER OR HOST_WASI)
+ add_library(mono-wasm-simd STATIC interp/interp-simd.c)
+ target_link_libraries (mono-wasm-simd PRIVATE monoapi eglib_api)
+ set_target_properties(mono-wasm-simd PROPERTIES COMPILE_FLAGS "-msimd128")
+ install(TARGETS mono-wasm-simd LIBRARY)
+endif()
+
+if(HOST_BROWSER OR HOST_WASI OR TARGET_WASM)
+ add_library(mono-wasm-nosimd STATIC interp/interp-nosimd.c)
+ target_link_libraries (mono-wasm-nosimd PRIVATE monoapi eglib_api)
+ install(TARGETS mono-wasm-nosimd LIBRARY)
+endif()
+
find_package(Python3 COMPONENTS Interpreter)
add_custom_command(
@@ -576,6 +594,9 @@ if(NOT DISABLE_EXECUTABLES)
endif()
endif()
target_link_libraries(mono-sgen PRIVATE monoapi eglib_api monosgen-static)
+ if (HOST_WASM)
+ target_link_libraries(mono-sgen PRIVATE mono-wasm-nosimd)
+ endif()
if(HAVE_ICU_SHIM)
target_link_libraries(mono-sgen PRIVATE icu_shim_objects)
endif()
diff --git a/src/mono/mono/mini/interp/interp-nosimd.c b/src/mono/mono/mini/interp/interp-nosimd.c
new file mode 100644
index 00000000000000..63bcf2783ec087
--- /dev/null
+++ b/src/mono/mono/mini/interp/interp-nosimd.c
@@ -0,0 +1,31 @@
+
+#include "interp-internals.h"
+#include "interp-simd.h"
+
+#ifdef INTERP_ENABLE_SIMD
+
+gboolean interp_simd_enabled = FALSE;
+
+#ifdef HOST_BROWSER
+
+int interp_simd_p_p_wasm_opcode_table [] = {
+};
+
+int interp_simd_p_pp_wasm_opcode_table [] = {
+};
+
+int interp_simd_p_ppp_wasm_opcode_table [] = {
+};
+
+#endif // HOST_BROWSER
+
+PP_SIMD_Method interp_simd_p_p_table [] = {
+};
+
+PPP_SIMD_Method interp_simd_p_pp_table [] = {
+};
+
+PPPP_SIMD_Method interp_simd_p_ppp_table [] = {
+};
+
+#endif // INTERP_ENABLE_SIMD
diff --git a/src/mono/mono/mini/interp/interp-simd.c b/src/mono/mono/mini/interp/interp-simd.c
index 65e60b4c6e7017..5031c87aaf206b 100644
--- a/src/mono/mono/mini/interp/interp-simd.c
+++ b/src/mono/mono/mini/interp/interp-simd.c
@@ -8,6 +8,8 @@
#ifdef INTERP_ENABLE_SIMD
+gboolean interp_simd_enabled = TRUE;
+
typedef gint64 v128_i8 __attribute__ ((vector_size (SIZEOF_V128)));
typedef guint64 v128_u8 __attribute__ ((vector_size (SIZEOF_V128)));
typedef gint32 v128_i4 __attribute__ ((vector_size (SIZEOF_V128)));
diff --git a/src/mono/mono/mini/interp/interp-simd.h b/src/mono/mono/mini/interp/interp-simd.h
index e3306a251fc9f6..8e0222613e44a2 100644
--- a/src/mono/mono/mini/interp/interp-simd.h
+++ b/src/mono/mono/mini/interp/interp-simd.h
@@ -3,6 +3,8 @@
#include
+extern gboolean interp_simd_enabled;
+
typedef void (*PP_SIMD_Method) (gpointer, gpointer);
typedef void (*PPP_SIMD_Method) (gpointer, gpointer, gpointer);
typedef void (*PPPP_SIMD_Method) (gpointer, gpointer, gpointer, gpointer);
diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c
index 255a2aba595634..7df7f92ab6d7c0 100644
--- a/src/mono/mono/mini/interp/transform-simd.c
+++ b/src/mono/mono/mini/interp/transform-simd.c
@@ -3,6 +3,7 @@
*/
#include "config.h"
+#include "interp-simd.h"
#include
#include
#include
@@ -900,6 +901,9 @@ interp_emit_simd_intrinsics (TransformData *td, MonoMethod *cmethod, MonoMethodS
if (image != mono_get_corlib ())
return FALSE;
+ if (!interp_simd_enabled)
+ return FALSE;
+
class_ns = m_class_get_name_space (cmethod->klass);
class_name = m_class_get_name (cmethod->klass);
diff --git a/src/mono/wasi/build/WasiApp.Native.targets b/src/mono/wasi/build/WasiApp.Native.targets
index 36c66585870a2c..ba9c085924d46a 100644
--- a/src/mono/wasi/build/WasiApp.Native.targets
+++ b/src/mono/wasi/build/WasiApp.Native.targets
@@ -273,6 +273,10 @@
<_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-wasm.a
+ <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-simd.a
+ <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' != 'true'">libmono-wasm-nosimd.a
+ <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' != 'true'">libmono-wasm-simd.a
+ <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-nosimd.a
@@ -286,7 +290,9 @@
Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)*.a"
Exclude="@(_MonoRuntimeComponentDontLink->'$(MicrosoftNetCoreAppRuntimePackRidNativeDir)%(Identity)')" />
<_WasmNativeFileForLinking Condition="'$(_WasmEHLib)' != ''" Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmEHLib)" />
+ <_WasmNativeFileForLinking Condition="'$(_WasmSIMDLib)' != ''" Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmSIMDLib)" />
<_WasmNativeFileForLinking Remove="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmEHLibToExclude)" />
+ <_WasmNativeFileForLinking Remove="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmSIMDLibToExclude)" />
<_WasmNativeFileForLinking Include="$(WasiSysRoot)\lib\wasm32-wasi\libc++.a" />
<_WasmNativeFileForLinking Include="$(WasiSysRoot)\lib\wasm32-wasi\libc++abi.a" />
diff --git a/src/mono/wasi/runtime/CMakeLists.txt b/src/mono/wasi/runtime/CMakeLists.txt
index ede21d72193f6c..912132b06ccfb0 100644
--- a/src/mono/wasi/runtime/CMakeLists.txt
+++ b/src/mono/wasi/runtime/CMakeLists.txt
@@ -26,6 +26,7 @@ target_link_libraries(dotnet
${MONO_ARTIFACTS_DIR}/libmono-ee-interp.a
${MONO_ARTIFACTS_DIR}/libmonosgen-2.0.a
${MONO_ARTIFACTS_DIR}/libmono-icall-table.a
+ ${MONO_ARTIFACTS_DIR}/libmono-wasm-${CONFIGURATION_INTERPSIMDTABLES_LIB}.a
${NATIVE_BIN_DIR}/wasm-bundled-timezones.a
${NATIVE_BIN_DIR}/libSystem.Native.a
${NATIVE_BIN_DIR}/libSystem.Globalization.Native.a
diff --git a/src/mono/wasi/wasi.proj b/src/mono/wasi/wasi.proj
index 611d7969f034b8..b942b6f4925035 100644
--- a/src/mono/wasi/wasi.proj
+++ b/src/mono/wasi/wasi.proj
@@ -218,6 +218,8 @@
$(CMakeBuildRuntimeConfigureCmd) -DICU_LIB_DIR="$(ICULibDir.TrimEnd('\/'))"$(CMakeBuildRuntimeConfigureCmd) -DMONO_ARTIFACTS_DIR="$(MonoArtifactsPath.TrimEnd('\/'))"$(CMakeBuildRuntimeConfigureCmd) -DNATIVE_BIN_DIR="$(NativeBinDir.TrimEnd('\/'))"
+ $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128" -DCONFIGURATION_INTERPSIMDTABLES_LIB="simd"
+ $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_INTERPSIMDTABLES_LIB="nosimd"$(CMakeBuildRuntimeConfigureCmd) -DDISABLE_THREADS=0call "$(RepositoryEngineeringDir)native\init-vs-env.cmd" wasm && $(CMakeBuildRuntimeConfigureCmd)
diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets
index 52125a8bd00b00..7060397f0cb85c 100644
--- a/src/mono/wasm/build/WasmApp.Native.targets
+++ b/src/mono/wasm/build/WasmApp.Native.targets
@@ -440,6 +440,10 @@
<_WasmEHLib Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-js.a
<_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' == 'true'">libmono-wasm-eh-js.a
<_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-wasm.a
+ <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-simd.a
+ <_WasmSIMDLib Condition="'$(WasmEnableSIMD)' != 'true'">libmono-wasm-nosimd.a
+ <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' != 'true'">libmono-wasm-simd.a
+ <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-nosimd.a
<_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]"
<_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]"
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')
@@ -460,7 +464,9 @@
Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)*.a"
Exclude="@(_MonoRuntimeComponentDontLink->'$(MicrosoftNetCoreAppRuntimePackRidNativeDir)%(Identity)')" />
<_WasmNativeFileForLinking Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmEHLib)" />
+ <_WasmNativeFileForLinking Condition="'$(_WasmSIMDLib)' != ''" Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmSIMDLib)" />
<_WasmNativeFileForLinking Remove="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmEHLibToExclude)" />
+ <_WasmNativeFileForLinking Remove="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(_WasmSIMDLibToExclude)" />
<_WasmExtraJSFile Include="@(Content)" Condition="'%(Content.Extension)' == '.js'" />
diff --git a/src/mono/wasm/runtime/CMakeLists.txt b/src/mono/wasm/runtime/CMakeLists.txt
index 6b8ef873ec27da..6d939088d74314 100644
--- a/src/mono/wasm/runtime/CMakeLists.txt
+++ b/src/mono/wasm/runtime/CMakeLists.txt
@@ -25,6 +25,7 @@ target_link_libraries(dotnet.native
${MONO_ARTIFACTS_DIR}/libmonosgen-2.0.a
${MONO_ARTIFACTS_DIR}/libmono-icall-table.a
${MONO_ARTIFACTS_DIR}/libmono-wasm-eh-js.a
+ ${MONO_ARTIFACTS_DIR}/libmono-wasm-${CONFIGURATION_INTERPSIMDTABLES_LIB}.a
${MONO_ARTIFACTS_DIR}/libmono-profiler-aot.a
${MONO_ARTIFACTS_DIR}/libmono-profiler-browser.a
${NATIVE_BIN_DIR}/wasm-bundled-timezones.a
diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj
index c46c92ab70db70..66bc509910571a 100644
--- a/src/mono/wasm/wasm.proj
+++ b/src/mono/wasm/wasm.proj
@@ -388,7 +388,8 @@
$(CMakeBuildRuntimeConfigureCmd) -DICU_LIB_DIR="$(ICULibDir.TrimEnd('\/').Replace('\','/'))"$(CMakeBuildRuntimeConfigureCmd) -DMONO_ARTIFACTS_DIR="$(MonoArtifactsPath.TrimEnd('\/').Replace('\','/'))"$(CMakeBuildRuntimeConfigureCmd) -DNATIVE_BIN_DIR="$(NativeBinDir.TrimEnd('\/').Replace('\','/'))"
- $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128"
+ $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS="-msimd128" -DCONFIGURATION_INTERPSIMDTABLES_LIB="simd"
+ $(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_INTERPSIMDTABLES_LIB="nosimd"$(CMakeBuildRuntimeConfigureCmd) -DDISABLE_THREADS=0$(CMakeBuildRuntimeConfigureCmd) -DDISABLE_LEGACY_JS_INTEROP=1$(CMakeBuildRuntimeConfigureCmd) $(CMakeConfigurationEmsdkPath)
From 92d1962d546e60172d69ecfda9e8c34123896732 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 18 Aug 2023 13:04:51 -0700
Subject: [PATCH 042/345] Disable BinderTracingTest.ResolutionFlow test
(#90818)
Tracking: #90580
Co-authored-by: Bruce Forstall
---
src/tests/issues.targets | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index 87f8bbf2673dd3..22178e4b3b506d 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -63,6 +63,9 @@
https://github.com/dotnet/runtime/issues/57786
+
+ https://github.com/dotnet/runtime/issues/90580
+ CoreCLR does not implement the mono embedding API
From 90b92bb265a412592c4c152983d7b30c92236dbe Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 18 Aug 2023 17:06:10 -0700
Subject: [PATCH 043/345] run nightlies against release/8.0 (#90809)
Co-authored-by: antonfirsov
---
eng/pipelines/libraries/stress/http.yml | 1 +
eng/pipelines/libraries/stress/ssl.yml | 1 +
2 files changed, 2 insertions(+)
diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml
index 6c740e49d04d47..f4f9c45de36e48 100644
--- a/eng/pipelines/libraries/stress/http.yml
+++ b/eng/pipelines/libraries/stress/http.yml
@@ -13,6 +13,7 @@ schedules:
- main
- release/6.0
- release/7.0
+ - release/8.0
variables:
- template: ../variables.yml
diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml
index 791251030f5753..ab93994400d346 100644
--- a/eng/pipelines/libraries/stress/ssl.yml
+++ b/eng/pipelines/libraries/stress/ssl.yml
@@ -13,6 +13,7 @@ schedules:
- main
- release/6.0
- release/7.0
+ - release/8.0
variables:
- template: ../variables.yml
From f8e2a9b9beccddae9f0838dd7a1bdcc3f994777e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 18 Aug 2023 18:17:18 -0700
Subject: [PATCH 044/345] Enable telemetry for WasmStripILAfterAOT (#90827)
Co-authored-by: Fan Yang
---
.../WorkloadTelemetry.targets | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
index 8f78ce16b62587..cf97ec1f14c2af 100644
--- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
+++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadTelemetry.targets
@@ -19,6 +19,7 @@
+
@@ -35,6 +36,7 @@
<_WorkloadUsesInterpreter Condition="'$(_WorkloadUsesInterpreter)' == '' and '$(UseInterpreter)' == 'true'">true
<_WorkloadUsesInterpreter Condition="'$(_WorkloadUsesInterpreter)' == '' and '$(RunAOTCompilation)' != 'true' and ('$(_WorkloadUsesBlazorWasm)' == 'true' or '$(_WorkloadUsesWasmSDK)' == 'true')">true
<_WorkloadUsesLibraryMode Condition="'$(NativeLib)' != '' and ('$(_WorkloadUsesMonoAOT)' == 'true' or '$(_WorkloadUsesNativeAOT)' == 'true')">true
+ <_WorkloadUsesWasmStripILAfterAOT Condition="'$(WasmStripILAfterAOT)' == 'true'">true
From 6aef01d5aae9dc0cd88c876a642cb06e4fcaafc4 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 18 Aug 2023 19:33:12 -0700
Subject: [PATCH 045/345] [release/8.0-rc1] [mini] Fix typo in
mono_decompose_vtype_opts (#90832)
* Fix typo in mono_decompose_vtype_opts
Without this, if some previous instruction already created a vreg for
ins->dest (for example if we are doing multiple passes over the basic
block because `restart == TRUE`) we will use an incorrect vreg when
decomposing the current VMOVE
Fixes https://github.com/dotnet/runtime/issues/90800
* Only emit an OP_LDTOKEN_FIELD if we loaded a field token
This is used by a CreateSpan optimization that needs access to the
MonoClassField*
For other cases of a bare LDTOKEN (such as hand-written IL that calls
LDTOKEN on a type but doesn't follow it up with a call to
`GetTypeFromHandle` leave the opcode as a VMOVE (from the
`EMIT_NEW_TEMPLOAD` above))
---------
Co-authored-by: Aleksey Kliger
---
src/mono/mono/mini/decompose.c | 2 +-
src/mono/mono/mini/method-to-ir.c | 13 ++++++++-----
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/mono/mono/mini/decompose.c b/src/mono/mono/mini/decompose.c
index b4570cc0c7429d..2be1ff52e416d0 100644
--- a/src/mono/mono/mini/decompose.c
+++ b/src/mono/mono/mini/decompose.c
@@ -1226,7 +1226,7 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
dest_var = get_vreg_to_inst (cfg, ins->dreg);
if (!src_var)
- src_var = mono_compile_create_var_for_vreg (cfg, m_class_get_byval_arg (ins->klass), OP_LOCAL, ins->dreg);
+ src_var = mono_compile_create_var_for_vreg (cfg, m_class_get_byval_arg (ins->klass), OP_LOCAL, ins->sreg1);
if (!dest_var)
dest_var = mono_compile_create_var_for_vreg (cfg, m_class_get_byval_arg (ins->klass), OP_LOCAL, ins->dreg);
diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c
index b5f75ea1c3133d..e3605981bafcdf 100644
--- a/src/mono/mono/mini/method-to-ir.c
+++ b/src/mono/mono/mini/method-to-ir.c
@@ -10840,12 +10840,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
- ins->opcode = OP_LDTOKEN_FIELD;
- ins->inst_c0 = n;
- ins->inst_p1 = handle;
+ if (handle_class == mono_defaults.fieldhandle_class) {
+ ins->opcode = OP_LDTOKEN_FIELD;
+ ins->inst_c0 = n;
+ ins->inst_p1 = handle;
+
+ cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE;
+ cfg->cbb->needs_decompose = TRUE;
+ }
- cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE;
- cfg->cbb->needs_decompose = TRUE;
}
}
From 034d27f4a9420e10601447d0385c88de9b4a2925 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Sat, 19 Aug 2023 09:13:47 -0700
Subject: [PATCH 046/345] [release/8.0-rc1] Use Roslyn interceptors feature in
binder gen (#90835)
* Use Roslyn interceptors feature in binder gen
* Fix polymorphic issue and address feedback
* Fix source build issue
* Revert changes to options gen
* Fix
* Work around source build issue
Co-authored-by: Eric StJohn
---------
Co-authored-by: Layomi Akinrinade
Co-authored-by: Eric StJohn
---
docs/project/list-of-diagnostics.md | 2 +
eng/SourceBuildPrebuiltBaseline.xml | 1 +
.../ConfigurationBindingGenerator.Emitter.cs | 87 +++----
.../ConfigurationBindingGenerator.Parser.cs | 69 ++++--
...onfigurationBindingGenerator.Suppressor.cs | 70 ++++++
.../gen/ConfigurationBindingGenerator.cs | 12 +-
.../Helpers/Emitter/ConfigurationBinder.cs | 146 ++++++------
...BindingHelper.cs => CoreBindingHelpers.cs} | 215 ++++++++----------
.../gen/Helpers/Emitter/Helpers.cs | 159 ++++++-------
.../OptionsBuilderConfigurationExtensions.cs | 44 ++--
...onfigurationServiceCollectionExtensions.cs | 49 ++--
.../gen/Helpers/InterceptorLocationInfo.cs | 90 ++++++++
.../gen/Helpers/MethodsToGen.cs | 9 +-
.../gen/Helpers/Parser/BinderInvocation.cs | 2 +-
.../gen/Helpers/Parser/ConfigurationBinder.cs | 33 ++-
.../OptionsBuilderConfigurationExtensions.cs | 44 ++--
...onfigurationServiceCollectionExtensions.cs | 4 +-
...nfiguration.Binder.SourceGeneration.csproj | 6 +-
.../gen/Model/ObjectSpec.cs | 4 -
.../gen/Model/ParsableFromStringSpec.cs | 2 +-
.../gen/Model/SourceGenerationSpec.cs | 8 +-
.../gen/Model/TypeSpec.cs | 9 +-
.../gen/Resources/Strings.resx | 4 +-
.../gen/Resources/xlf/Strings.cs.xlf | 8 +-
.../gen/Resources/xlf/Strings.de.xlf | 8 +-
.../gen/Resources/xlf/Strings.es.xlf | 8 +-
.../gen/Resources/xlf/Strings.fr.xlf | 8 +-
.../gen/Resources/xlf/Strings.it.xlf | 8 +-
.../gen/Resources/xlf/Strings.ja.xlf | 8 +-
.../gen/Resources/xlf/Strings.ko.xlf | 8 +-
.../gen/Resources/xlf/Strings.pl.xlf | 8 +-
.../gen/Resources/xlf/Strings.pt-BR.xlf | 8 +-
.../gen/Resources/xlf/Strings.ru.xlf | 8 +-
.../gen/Resources/xlf/Strings.tr.xlf | 8 +-
.../gen/Resources/xlf/Strings.zh-Hans.xlf | 8 +-
.../gen/Resources/xlf/Strings.zh-Hant.xlf | 8 +-
.../tests/Common/ConfigurationBinderTests.cs | 3 +-
.../Baselines/Collections.generated.txt | 79 ++-----
.../ConfigurationBinder/Bind.generated.txt | 100 +++++---
.../Bind_Instance.generated.txt | 60 +++--
.../Bind_Instance_BinderOptions.generated.txt | 62 ++---
.../Bind_Key_Instance.generated.txt | 60 +++--
.../ConfigurationBinder/Get.generated.txt | 81 +++----
.../GetValue.generated.txt | 57 +++--
.../GetValue_T_Key.generated.txt | 29 ++-
.../GetValue_T_Key_DefaultValue.generated.txt | 29 ++-
.../GetValue_TypeOf_Key.generated.txt | 29 ++-
...alue_TypeOf_Key_DefaultValue.generated.txt | 29 ++-
.../ConfigurationBinder/Get_T.generated.txt | 54 ++---
.../Get_T_BinderOptions.generated.txt | 54 ++---
.../Get_TypeOf.generated.txt | 39 ++--
.../Get_TypeOf_BinderOptions.generated.txt | 39 ++--
.../BindConfiguration.generated.txt | 96 +++++---
.../OptionsBuilder/Bind_T.generated.txt | 117 +++++-----
.../Bind_T_BinderOptions.generated.txt | 105 +++++----
.../Baselines/Primitives.generated.txt | 45 +++-
.../Configure_T.generated.txt | 101 ++++----
.../Configure_T_BinderOptions.generated.txt | 101 ++++----
.../Configure_T_name.generated.txt | 101 ++++----
...nfigure_T_name_BinderOptions.generated.txt | 91 ++++----
...BindingGeneratorTests.Baselines.Options.cs | 4 +
...gurationBindingGeneratorTests.Baselines.cs | 4 +-
.../ConfigurationBindingGeneratorTests.cs | 18 +-
...ation.Binder.SourceGeneration.Tests.csproj | 2 +-
...ft.Extensions.Logging.Configuration.csproj | 1 +
...icrosoft.Extensions.Logging.Console.csproj | 2 +
...onExtensions.SourceGeneration.Tests.csproj | 4 +-
67 files changed, 1581 insertions(+), 1188 deletions(-)
create mode 100644 src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Suppressor.cs
rename src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/{CoreBindingHelper.cs => CoreBindingHelpers.cs} (83%)
create mode 100644 src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/InterceptorLocationInfo.cs
diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md
index 4f78e9e711653d..579b8d160d59b0 100644
--- a/docs/project/list-of-diagnostics.md
+++ b/docs/project/list-of-diagnostics.md
@@ -270,3 +270,5 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| Suppression ID | Suppressed Diagnostic ID | Description |
| :----------------------- | :----------------------- | :---------- |
| __`SYSLIBSUPPRESS0001`__ | CA1822 | Do not offer to make methods static when the methods need to be instance methods for a custom marshaller shape. |
+| __`SYSLIBSUPPRESS0002`__ | IL2026 | ConfigurationBindingGenerator: suppress RequiresUnreferencedCode diagnostic for binding call that has been intercepted by a generated static variant. |
+| __`SYSLIBSUPPRESS0003`__ | IL3050 | ConfigurationBindingGenerator: suppress RequiresDynamicCode diagnostic for binding call that has been intercepted by a generated static variant. |
diff --git a/eng/SourceBuildPrebuiltBaseline.xml b/eng/SourceBuildPrebuiltBaseline.xml
index 74f6be96543a5e..46dd7457d764aa 100644
--- a/eng/SourceBuildPrebuiltBaseline.xml
+++ b/eng/SourceBuildPrebuiltBaseline.xml
@@ -10,6 +10,7 @@
+
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs
index a40cf2976b31fc..756e10bc26b8d5 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Immutable;
using System.Diagnostics;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;
@@ -17,7 +18,6 @@ private sealed partial class Emitter
private readonly SourceGenerationSpec _sourceGenSpec;
private bool _emitBlankLineBeforeNextStatement;
- private bool _useFullyQualifiedNames;
private int _valueSuffixIndex;
private static readonly Regex s_arrayBracketsRegex = new(Regex.Escape("[]"));
@@ -32,7 +32,7 @@ public Emitter(SourceProductionContext context, SourceGenerationSpec sourceGenSp
public void Emit()
{
- if (!ShouldEmitBinders())
+ if (!ShouldEmitBindingExtensions())
{
return;
}
@@ -42,17 +42,26 @@ public void Emit()
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
""");
- _writer.WriteLine();
- _useFullyQualifiedNames = true;
- EmitBinder_Extensions_IConfiguration();
- EmitBinder_Extensions_OptionsBuilder();
- EmitBinder_Extensions_IServiceCollection();
+ EmitInterceptsLocationAttrDecl();
+
+ EmitStartBlock($"namespace {ProjectName}");
+ EmitUsingStatements();
+
+ _writer.WriteLine();
+ EmitStartBlock($$"""
+ {{Expression.GeneratedCodeAnnotation}}
+ file static class {{Identifier.BindingExtensions}}
+ """);
+ EmitBindingExtensions_IConfiguration();
+ EmitBindingExtensions_OptionsBuilder();
+ EmitBindingExtensions_IServiceCollection();
+ EmitCoreBindingHelpers();
+ EmitEndBlock(); // BindingExtensions class
- _useFullyQualifiedNames = false;
- Emit_CoreBindingHelper();
+ EmitEndBlock(); // Binding namespace.
- _context.AddSource($"{Identifier.GeneratedConfigurationBinder}.g.cs", _writer.ToSourceText());
+ _context.AddSource($"{Identifier.BindingExtensions}.g.cs", _writer.ToSourceText());
}
private void EmitBindCoreCall(
@@ -74,7 +83,7 @@ private void EmitBindCoreCall(
if (initKind is InitializationKind.AssignmentWithNullCheck)
{
Debug.Assert(!type.IsValueType);
- _writer.WriteLine($"{type.MinimalDisplayString}? {tempIdentifier} = {memberAccessExpr};");
+ _writer.WriteLine($"{type.DisplayString}? {tempIdentifier} = {memberAccessExpr};");
EmitBindCoreCall(tempIdentifier, InitializationKind.AssignmentWithNullCheck);
}
else if (initKind is InitializationKind.None && type.IsValueType)
@@ -89,9 +98,7 @@ private void EmitBindCoreCall(
void EmitBindCoreCall(string objExpression, InitializationKind initKind)
{
- string methodDisplayString = GetHelperMethodDisplayString(nameof(MethodsToGen_CoreBindingHelper.BindCore));
- string bindCoreCall = $@"{methodDisplayString}({configArgExpr}, ref {objExpression}, {Identifier.binderOptions});";
-
+ string bindCoreCall = $@"{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configArgExpr}, ref {objExpression}, {Identifier.binderOptions});";
EmitObjectInit(objExpression, initKind);
_writer.WriteLine(bindCoreCall);
writeOnSuccess?.Invoke(objExpression);
@@ -127,12 +134,11 @@ private void EmitBindLogicFromString(
}
else if (typeKind is StringParsableTypeKind.Enum)
{
- parsedValueExpr = $"ParseEnum<{type.MinimalDisplayString}>({stringValueToParse_Expr}, () => {sectionPathExpr})";
+ parsedValueExpr = $"ParseEnum<{type.DisplayString}>({stringValueToParse_Expr}, () => {sectionPathExpr})";
}
else
{
- string helperMethodDisplayString = GetHelperMethodDisplayString(type.ParseMethodName);
- parsedValueExpr = $"{helperMethodDisplayString}({stringValueToParse_Expr}, () => {sectionPathExpr})";
+ parsedValueExpr = $"{type.ParseMethodName}({stringValueToParse_Expr}, () => {sectionPathExpr})";
}
if (!checkForNullSectionValue)
@@ -156,7 +162,7 @@ private bool EmitObjectInit(TypeSpec type, string memberAccessExpr, Initializati
string initExpr;
CollectionSpec? collectionType = type as CollectionSpec;
- string effectiveDisplayString = GetTypeDisplayString(type);
+ string effectiveDisplayString = type.DisplayString;
if (collectionType is not null)
{
if (collectionType is EnumerableSpec { InitializationStrategy: InitializationStrategy.Array })
@@ -165,7 +171,7 @@ private bool EmitObjectInit(TypeSpec type, string memberAccessExpr, Initializati
}
else
{
- effectiveDisplayString = GetTypeDisplayString(collectionType.ConcreteType ?? collectionType);
+ effectiveDisplayString = (collectionType.ConcreteType ?? collectionType).DisplayString;
initExpr = $"new {effectiveDisplayString}()";
}
}
@@ -215,36 +221,41 @@ private bool EmitObjectInit(TypeSpec type, string memberAccessExpr, Initializati
return true;
}
- private void EmitCastToIConfigurationSection()
+ private void EmitInterceptsLocationAttrDecl()
{
- string sectionTypeDisplayString;
- string exceptionTypeDisplayString;
- if (_useFullyQualifiedNames)
- {
- sectionTypeDisplayString = "global::Microsoft.Extensions.Configuration.IConfigurationSection";
- exceptionTypeDisplayString = FullyQualifiedDisplayString.InvalidOperationException;
- }
- else
- {
- sectionTypeDisplayString = Identifier.IConfigurationSection;
- exceptionTypeDisplayString = nameof(InvalidOperationException);
- }
-
+ _writer.WriteLine();
_writer.WriteLine($$"""
- if ({{Identifier.configuration}} is not {{sectionTypeDisplayString}} {{Identifier.section}})
+ namespace System.Runtime.CompilerServices
{
- throw new {{exceptionTypeDisplayString}}();
+ using System;
+ using System.CodeDom.Compiler;
+
+ {{Expression.GeneratedCodeAnnotation}}
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
""");
+ _writer.WriteLine();
+ }
+
+ private void EmitUsingStatements()
+ {
+ foreach (string @namespace in _sourceGenSpec.Namespaces.ToImmutableSortedSet())
+ {
+ _writer.WriteLine($"using {@namespace};");
+ }
}
private void EmitIConfigurationHasValueOrChildrenCheck(bool voidReturn)
{
string returnPostfix = voidReturn ? string.Empty : " null";
- string methodDisplayString = GetHelperMethodDisplayString(Identifier.HasValueOrChildren);
-
_writer.WriteLine($$"""
- if (!{{methodDisplayString}}({{Identifier.configuration}}))
+ if (!{{Identifier.HasValueOrChildren}}({{Identifier.configuration}}))
{
return{{returnPostfix}};
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs
index b0f53ef074078f..64db4eb58b1f77 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs
@@ -1,12 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Operations;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
@@ -147,7 +149,7 @@ type.TypeKind is TypeKind.TypeParameter or TypeKind.Pointer or TypeKind.Error ||
{
// List is used in generated code as a temp holder for formatting
// an error for config properties that don't map to object properties.
- _sourceGenSpec.TypeNamespaces.Add("System.Collections.Generic");
+ _sourceGenSpec.Namespaces.Add("System.Collections.Generic");
spec = CreateObjectSpec(namedType);
}
@@ -169,32 +171,54 @@ type.TypeKind is TypeKind.TypeParameter or TypeKind.Pointer or TypeKind.Error ||
string @namespace = spec.Namespace;
if (@namespace is not null and not "")
{
- _sourceGenSpec.TypeNamespaces.Add(@namespace);
+ _sourceGenSpec.Namespaces.Add(@namespace);
}
return _createdSpecs[type] = spec;
}
- private void RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper method, TypeSpec type)
+ private void RegisterTypeForBindCoreMainGen(TypeSpec typeSpec)
{
- if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(method, out HashSet? types))
+ if (typeSpec.NeedsMemberBinding)
{
- _sourceGenSpec.TypesForGen_CoreBindingHelper_Methods[method] = types = new HashSet();
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCoreMain, typeSpec);
+ RegisterTypeForBindCoreGen(typeSpec);
+ _sourceGenSpec.MethodsToGen_CoreBindingHelper |= MethodsToGen_CoreBindingHelper.AsConfigWithChildren;
}
-
- types.Add(type);
- _sourceGenSpec.MethodsToGen_CoreBindingHelper |= method;
}
- private void RegisterTypeForBindCoreUntypedGen(TypeSpec typeSpec)
+ private void RegisterTypeForBindCoreGen(TypeSpec typeSpec)
{
if (typeSpec.NeedsMemberBinding)
{
RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, typeSpec);
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCoreUntyped, typeSpec);
}
}
+ private void RegisterTypeForGetCoreGen(TypeSpec typeSpec)
+ {
+ RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.GetCore, typeSpec);
+ _sourceGenSpec.MethodsToGen_CoreBindingHelper |= MethodsToGen_CoreBindingHelper.AsConfigWithChildren;
+ }
+
+ private void RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper method, TypeSpec type)
+ {
+ if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(method, out HashSet? types))
+ {
+ _sourceGenSpec.TypesForGen_CoreBindingHelper_Methods[method] = types = new HashSet();
+ }
+
+ types.Add(type);
+ _sourceGenSpec.MethodsToGen_CoreBindingHelper |= method;
+ }
+
+ ///
+ /// Registers interceptors for root binding methods, except for ConfigurationBinder.Bind,
+ /// which is handled by
+ ///
+ private void RegisterAsInterceptor(Enum method, IInvocationOperation operation) =>
+ _sourceGenSpec.InterceptionInfo.RegisterCacheEntry(method, new InterceptorLocationInfo(operation));
+
private static bool IsNullable(ITypeSymbol type, [NotNullWhen(true)] out ITypeSymbol? underlyingType)
{
if (type is INamedTypeSymbol { IsGenericType: true } genericType &&
@@ -335,7 +359,7 @@ private bool TryGetTypeSpec(ITypeSymbol type, DiagnosticDescriptor descriptor, o
// We want a BindCore method for List as a temp holder for the array values. We know the element type is supported.
EnumerableSpec listSpec = (GetOrCreateTypeSpec(_typeSymbols.List.Construct(arrayType.ElementType)) as EnumerableSpec)!;
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, listSpec);
+ RegisterTypeForBindCoreGen(listSpec);
EnumerableSpec spec = new EnumerableSpec(arrayType)
{
@@ -347,7 +371,7 @@ private bool TryGetTypeSpec(ITypeSymbol type, DiagnosticDescriptor descriptor, o
};
Debug.Assert(spec.CanInitialize);
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, spec);
+ RegisterTypeForBindCoreGen(spec);
return spec;
}
@@ -383,7 +407,7 @@ private bool IsSupportedArrayType(ITypeSymbol type)
if (spec is not null)
{
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, spec);
+ RegisterTypeForBindCoreGen(spec);
spec.InitExceptionMessage ??= spec.ElementType.InitExceptionMessage;
}
@@ -442,7 +466,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, ITypeSymbol k
constructionStrategy = InitializationStrategy.ToEnumerableMethod;
populationStrategy = CollectionPopulationStrategy.Cast_Then_Add;
toEnumerableMethodCall = "ToDictionary(pair => pair.Key, pair => pair.Value)";
- _sourceGenSpec.TypeNamespaces.Add("System.Linq");
+ _sourceGenSpec.Namespaces.Add("System.Linq");
}
else
{
@@ -711,7 +735,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, ITypeSymbol k
if (objectSpec.NeedsMemberBinding)
{
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.BindCore, objectSpec);
+ RegisterTypeForBindCoreGen(objectSpec);
}
return objectSpec;
@@ -890,4 +914,19 @@ private void RegisterTypeDiagnostic(ITypeSymbol causingType, InvocationDiagnosti
}
}
}
+
+ public static class ParserExtensions
+ {
+ public static void RegisterCacheEntry(this Dictionary cache, TKey key, TEntry entry)
+ where TKey : notnull
+ where TValue : ICollection, new()
+ {
+ if (!cache.TryGetValue(key, out TValue? entryCollection))
+ {
+ cache[key] = entryCollection = new TValue();
+ }
+
+ entryCollection.Add(entry);
+ }
+ }
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Suppressor.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Suppressor.cs
new file mode 100644
index 00000000000000..13158753c3f075
--- /dev/null
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Suppressor.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Operations;
+
+namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
+{
+ public sealed partial class ConfigurationBindingGenerator
+ {
+ ///
+ /// Supresses false-positive diagnostics emitted by the linker
+ /// when analyzing binding invocations that we have intercepted.
+ /// Workaround for https://github.com/dotnet/roslyn/issues/68669.
+ ///
+ [DiagnosticAnalyzer(LanguageNames.CSharp)]
+ public sealed class Suppressor : DiagnosticSuppressor
+ {
+ private const string Justification = "The target method has been intercepted by a generated static variant.";
+
+ ///
+ /// Suppression descriptor for IL2026: Members attributed with RequiresUnreferencedCode may break when trimming.
+ ///
+ private static readonly SuppressionDescriptor RUCDiagnostic = new(id: "SYSLIBSUPPRESS0002", suppressedDiagnosticId: "IL2026", Justification);
+
+ ///
+ /// Suppression descriptor for IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as native AOT.
+ ///
+ private static readonly SuppressionDescriptor RDCDiagnostic = new(id: "SYSLIBSUPPRESS0003", suppressedDiagnosticId: "IL3050", Justification);
+
+ public override ImmutableArray SupportedSuppressions => ImmutableArray.Create(RUCDiagnostic, RDCDiagnostic);
+
+ public override void ReportSuppressions(SuppressionAnalysisContext context)
+ {
+ foreach (Diagnostic diagnostic in context.ReportedDiagnostics)
+ {
+ string diagnosticId = diagnostic.Id;
+
+ if (diagnosticId != RDCDiagnostic.SuppressedDiagnosticId && diagnosticId != RUCDiagnostic.SuppressedDiagnosticId)
+ {
+ continue;
+ }
+
+ Location location = diagnostic.AdditionalLocations.Count > 0
+ ? diagnostic.AdditionalLocations[0]
+ : diagnostic.Location;
+
+ bool shouldSuppressDiagnostic =
+ location.SourceTree is SyntaxTree sourceTree &&
+ sourceTree.GetRoot().FindNode(location.SourceSpan) is SyntaxNode syntaxNode &&
+ BinderInvocation.IsCandidateSyntaxNode(syntaxNode) &&
+ context.GetSemanticModel(sourceTree)
+ .GetOperation((InvocationExpressionSyntax)syntaxNode, context.CancellationToken) is IInvocationOperation operation &&
+ BinderInvocation.IsBindingOperation(operation);
+
+ if (shouldSuppressDiagnostic)
+ {
+ SuppressionDescriptor targetSuppression = diagnosticId == RUCDiagnostic.SuppressedDiagnosticId
+ ? RUCDiagnostic
+ : RDCDiagnostic;
+ context.ReportSuppression(Suppression.Create(targetSuppression, diagnostic));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs
index 70da582dddf0cd..fbca2dd3cfc507 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs
@@ -5,7 +5,6 @@
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
@@ -15,7 +14,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
[Generator]
public sealed partial class ConfigurationBindingGenerator : IIncrementalGenerator
{
- internal const string ProjectName = "Microsoft.Extensions.Configuration.Binder.SourceGeneration";
+ private static readonly string ProjectName = Emitter.s_assemblyName.Name;
public void Initialize(IncrementalGeneratorInitializationContext context)
{
@@ -42,9 +41,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
context.RegisterSourceOutput(inputData, (spc, source) => Execute(source.Item1, source.Item2, spc));
}
- ///
- /// Generates source code to optimize binding with ConfigurationBinder.
- ///
private static void Execute(CompilationData compilationData, ImmutableArray inputCalls, SourceProductionContext context)
{
if (inputCalls.IsDefaultOrEmpty)
@@ -73,7 +69,11 @@ private sealed record CompilationData
public CompilationData(CSharpCompilation compilation)
{
- LanguageVersionIsSupported = compilation.LanguageVersion >= LanguageVersion.CSharp11;
+ // We don't have a CSharp21 value available yet. Polyfill the value here for forward compat, rather than use the LangugeVersion.Preview enum value.
+ // https://github.com/dotnet/roslyn/blob/168689931cb4e3150641ec2fb188a64ce4b3b790/src/Compilers/CSharp/Portable/LanguageVersion.cs#L218-L232
+ const int LangVersion_CSharp12 = 1200;
+ LanguageVersionIsSupported = (int)compilation.LanguageVersion >= LangVersion_CSharp12;
+
if (LanguageVersionIsSupported)
{
TypeSymbols = new KnownTypeSymbols(compilation);
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/ConfigurationBinder.cs
index c10e607df75d0a..64064887c7c70b 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/ConfigurationBinder.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/ConfigurationBinder.cs
@@ -2,9 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using Microsoft.CodeAnalysis;
+using SourceGenerators;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
@@ -14,91 +12,84 @@ private sealed partial class Emitter
{
private bool ShouldEmitMethods(MethodsToGen_ConfigurationBinder methods) => (_sourceGenSpec.MethodsToGen_ConfigurationBinder & methods) != 0;
- private void EmitBinder_Extensions_IConfiguration()
+ private void EmitBindingExtensions_IConfiguration()
{
- Debug.Assert(_sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods.Count <= 3 &&
- !_sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods.Keys.Any(overload => (overload & MethodsToGen_ConfigurationBinder.Bind) is 0));
-
if (!ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Any))
{
return;
}
- _emitBlankLineBeforeNextStatement = false;
- EmitRootBindingClassStartBlock(Identifier.GeneratedConfigurationBinder);
-
+ EmitBindingExtStartRegion(Identifier.IConfiguration);
EmitGetMethods();
EmitGetValueMethods();
EmitBindMethods_ConfigurationBinder();
-
- EmitEndBlock();
- _emitBlankLineBeforeNextStatement = true;
+ EmitBindingExtEndRegion();
}
private void EmitGetMethods()
{
- const string expressionForGetCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{nameof(MethodsToGen_CoreBindingHelper.GetCore)}";
+ const string expressionForGetCore = nameof(MethodsToGen_CoreBindingHelper.GetCore);
const string documentation = "Attempts to bind the configuration instance to a new instance of type T.";
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_T))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.Get}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_T, documentation);
+ _writer.WriteLine($"public static T? {Identifier.Get}(this {Identifier.IConfiguration} {Identifier.configuration}) => " +
$"(T?)({expressionForGetCore}({Identifier.configuration}, typeof(T), {Identifier.configureOptions}: null) ?? default(T));");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_T_BinderOptions))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.Get}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_T_BinderOptions, documentation);
+ _writer.WriteLine($"public static T? {Identifier.Get}(this {Identifier.IConfiguration} {Identifier.configuration}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}) => " +
$"(T?)({expressionForGetCore}({Identifier.configuration}, typeof(T), {Identifier.configureOptions}) ?? default(T));");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_TypeOf))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.Get}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_TypeOf, documentation);
+ _writer.WriteLine($"public static object? {Identifier.Get}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}) => " +
$"{expressionForGetCore}({Identifier.configuration}, {Identifier.type}, {Identifier.configureOptions}: null);");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Get_TypeOf_BinderOptions))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.Get}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.Get_TypeOf_BinderOptions, documentation);
+ _writer.WriteLine($"public static object? {Identifier.Get}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}) => " +
$"{expressionForGetCore}({Identifier.configuration}, {Identifier.type}, {Identifier.configureOptions});");
}
}
private void EmitGetValueMethods()
{
- const string expressionForGetValueCore = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{nameof(MethodsToGen_CoreBindingHelper.GetValueCore)}";
+ const string expressionForGetValueCore = $"{Identifier.BindingExtensions}.{nameof(MethodsToGen_CoreBindingHelper.GetValueCore)}";
const string documentation = "Extracts the value with the specified key and converts it to the specified type.";
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_T_key))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.GetValue}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, string {Identifier.key}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_T_key, documentation);
+ _writer.WriteLine($"public static T? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, string {Identifier.key}) => " +
$"(T?)({expressionForGetValueCore}({Identifier.configuration}, typeof(T), {Identifier.key}) ?? default(T));");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_T_key_defaultValue))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static T? {Identifier.GetValue}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, string {Identifier.key}, T {Identifier.defaultValue}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_T_key_defaultValue, documentation);
+ _writer.WriteLine($"public static T? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, string {Identifier.key}, T {Identifier.defaultValue}) => " +
$"(T?)({expressionForGetValueCore}({Identifier.configuration}, typeof(T), {Identifier.key}) ?? {Identifier.defaultValue});");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.GetValue}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}, string {Identifier.key}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key, documentation);
+ _writer.WriteLine($"public static object? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key}) => " +
$"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key});");
}
if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key_defaultValue))
{
- StartMethodDefinition(documentation);
- _writer.WriteLine($"public static object? {Identifier.GetValue}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayString.Type} {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " +
+ StartMethodDefinition(MethodsToGen_ConfigurationBinder.GetValue_TypeOf_key_defaultValue, documentation);
+ _writer.WriteLine($"public static object? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " +
$"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key}) ?? {Identifier.defaultValue};");
}
}
@@ -110,72 +101,71 @@ private void EmitBindMethods_ConfigurationBinder()
return;
}
- Dictionary> types = _sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods;
+ string objParamExpr = $"object? {Identifier.obj}";
- if (types.TryGetValue(MethodsToGen_ConfigurationBinder.Bind_instance, out HashSet? typeSpecs))
+ if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_instance))
{
- foreach (TypeSpec type in typeSpecs)
- {
- EmitMethodImplementation(
- type,
- additionalParams: GetObjParameter(type),
- configExpression: Identifier.configuration,
- configureOptions: false);
- }
+ EmitMethods(
+ MethodsToGen_ConfigurationBinder.Bind_instance,
+ additionalParams: objParamExpr,
+ configExpression: Identifier.configuration,
+ configureOptions: false);
}
- if (types.TryGetValue(MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions, out typeSpecs))
+ if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions))
{
- foreach (TypeSpec type in typeSpecs)
- {
- EmitMethodImplementation(
- type,
- additionalParams: $"{GetObjParameter(type)}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}",
- configExpression: Identifier.configuration,
- configureOptions: true);
- }
+ EmitMethods(
+ MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions,
+ additionalParams: $"{objParamExpr}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}",
+ configExpression: Identifier.configuration,
+ configureOptions: true);
}
- if (types.TryGetValue(MethodsToGen_ConfigurationBinder.Bind_key_instance, out typeSpecs))
+ if (ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_key_instance))
{
- foreach (TypeSpec type in typeSpecs)
- {
- EmitMethodImplementation(
- type,
- additionalParams: $"string {Identifier.key}, {GetObjParameter(type)}",
- configExpression: $"{Expression.configurationGetSection}({Identifier.key})",
- configureOptions: false);
- }
+ EmitMethods(
+ MethodsToGen_ConfigurationBinder.Bind_key_instance,
+ additionalParams: $"string {Identifier.key}, {objParamExpr}",
+ configExpression: $"{Expression.configurationGetSection}({Identifier.key})",
+ configureOptions: false);
}
- void EmitMethodImplementation(TypeSpec type, string additionalParams, string configExpression, bool configureOptions)
+ void EmitMethods(MethodsToGen_ConfigurationBinder method, string additionalParams, string configExpression, bool configureOptions)
{
- string binderOptionsArg = configureOptions ? $"{Expression.GetBinderOptions}({Identifier.configureOptions})" : $"{Identifier.binderOptions}: null";
-
- string returnExpression;
- if (type.CanInitialize)
+ foreach (KeyValuePair> pair in _sourceGenSpec.InterceptionInfo_ConfigBinder.GetOverloadInfo(method))
{
- returnExpression = type.NeedsMemberBinding
- ? $"{FullyQualifiedDisplayString.CoreBindingHelper}.{nameof(MethodsToGen_CoreBindingHelper.BindCore)}({configExpression}, ref {Identifier.obj}, {binderOptionsArg})"
- : "{ }";
+ (TypeSpec type, List interceptorInfoList) = (pair.Key, pair.Value);
+
+ EmitBlankLineIfRequired();
+ _writer.WriteLine($"/// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.");
+ EmitInterceptsLocationAnnotations(interceptorInfoList);
+ EmitStartBlock($"public static void {Identifier.Bind}_{type.DisplayString.ToIdentifierSubstring()}(this {Identifier.IConfiguration} {Identifier.configuration}, {additionalParams})");
+
+ if (!EmitInitException(type) && type.NeedsMemberBinding)
+ {
+ string binderOptionsArg = configureOptions ? $"{Identifier.GetBinderOptions}({Identifier.configureOptions})" : $"{Identifier.binderOptions}: null";
+
+ EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
+ if (!type.IsValueType)
+ {
+ EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
+ }
+ _writer.WriteLine($$"""
+ var {{Identifier.typedObj}} = ({{type.EffectiveType.DisplayString}}){{Identifier.obj}};
+ {{nameof(MethodsToGen_CoreBindingHelper.BindCore)}}({{configExpression}}, ref {{Identifier.typedObj}}, {{binderOptionsArg}});
+ """);
+ }
+
+ EmitEndBlock();
}
- else
- {
- returnExpression = GetInitException(type.InitExceptionMessage);
- }
-
- StartMethodDefinition("Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.");
- _writer.WriteLine($"public static void {Identifier.Bind}(this {FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}, {additionalParams}) => "
- + $"{returnExpression};");
}
-
- string GetObjParameter(TypeSpec type) => $"{type.FullyQualifiedDisplayString} {Identifier.obj}";
}
- private void StartMethodDefinition(string documentation)
+ private void StartMethodDefinition(MethodsToGen_ConfigurationBinder method, string documentation)
{
EmitBlankLineIfRequired();
_writer.WriteLine($"/// {documentation}");
+ EmitInterceptsLocationAnnotations(method);
}
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelper.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelpers.cs
similarity index 83%
rename from src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelper.cs
rename to src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelpers.cs
index a7b42b1329804e..f30408fad596dd 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelper.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelpers.cs
@@ -3,10 +3,10 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis;
+using SourceGenerators;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
@@ -16,41 +16,18 @@ private sealed partial class Emitter
{
private bool ShouldEmitMethods(MethodsToGen_CoreBindingHelper methods) => (_sourceGenSpec.MethodsToGen_CoreBindingHelper & methods) != 0;
- private void Emit_CoreBindingHelper()
+ private void EmitCoreBindingHelpers()
{
Debug.Assert(_emitBlankLineBeforeNextStatement);
- _writer.WriteLine();
- _emitBlankLineBeforeNextStatement = false;
-
- EmitStartBlock($"namespace {ProjectName}");
- EmitHelperUsingStatements();
-
- _writer.WriteLine();
-
- EmitStartBlock($$"""
- /// Provide core binding logic.
- {{GetGeneratedCodeAttributeSrc()}}
- file static class {{Identifier.CoreBindingHelper}}
- """);
-
+ EmitBindingExtStartRegion("Core binding");
EmitConfigurationKeyCaches();
EmitGetCoreMethod();
EmitGetValueCoreMethod();
- EmitBindCoreUntypedMethod();
+ EmitBindCoreMainMethod();
EmitBindCoreMethods();
EmitInitializeMethods();
EmitHelperMethods();
-
- EmitEndBlock(); // End helper class.
- EmitEndBlock(); // End namespace.
- }
-
- private void EmitHelperUsingStatements()
- {
- foreach (string @namespace in _sourceGenSpec.TypeNamespaces.ToImmutableSortedSet())
- {
- _writer.WriteLine($"using {@namespace};");
- }
+ EmitBindingExtEndRegion();
}
private void EmitConfigurationKeyCaches()
@@ -60,6 +37,8 @@ private void EmitConfigurationKeyCaches()
return;
}
+ EmitBlankLineIfRequired();
+
foreach (TypeSpec type in targetTypes)
{
if (type is not ObjectSpec objectType)
@@ -73,10 +52,8 @@ private void EmitConfigurationKeyCaches()
string configKeysSource = string.Join(", ", keys);
string fieldName = GetConfigKeyCacheFieldName(objectType);
- _writer.WriteLine($@"private readonly static Lazy<{MinimalDisplayString.HashSetOfString}> {fieldName} = new(() => new {MinimalDisplayString.HashSetOfString}(StringComparer.OrdinalIgnoreCase) {{ {configKeysSource} }});");
+ _writer.WriteLine($@"private readonly static Lazy<{TypeDisplayString.HashSetOfString}> {fieldName} = new(() => new {TypeDisplayString.HashSetOfString}(StringComparer.OrdinalIgnoreCase) {{ {configKeysSource} }});");
}
-
- _emitBlankLineBeforeNextStatement = true;
}
private void EmitGetCoreMethod()
@@ -96,16 +73,24 @@ private void EmitGetCoreMethod()
EmitIConfigurationHasValueOrChildrenCheck(voidReturn: false);
+ bool isFirstType = true;
foreach (TypeSpec type in types)
{
TypeSpec effectiveType = type.EffectiveType;
TypeSpecKind kind = effectiveType.SpecKind;
+ string conditionKindExpr = GetConditionKindExpr(ref isFirstType);
- EmitStartBlock($"if (type == typeof({type.MinimalDisplayString}))");
+ EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
if (effectiveType is ParsableFromStringSpec stringParsableType)
{
- EmitCastToIConfigurationSection();
+ _writer.WriteLine($$"""
+ if ({{Identifier.configuration}} is not {{Identifier.IConfigurationSection}} {{Identifier.section}})
+ {
+ throw new {{Identifier.InvalidOperationException}}();
+ }
+ """);
+
EmitBindLogicFromString(
stringParsableType,
Expression.sectionValue,
@@ -121,9 +106,9 @@ private void EmitGetCoreMethod()
}
EmitEndBlock();
- _writer.WriteLine();
}
+ _writer.WriteLine();
Emit_NotSupportedException_TypeNotDetectedAsInput();
EmitEndBlock();
_emitBlankLineBeforeNextStatement = true;
@@ -152,9 +137,11 @@ private void EmitGetValueCoreMethod()
_writer.WriteLine();
+ bool isFirstType = true;
foreach (TypeSpec type in targetTypes)
{
- EmitStartBlock($"if ({Identifier.type} == typeof({type.MinimalDisplayString}))");
+ string conditionKindExpr = GetConditionKindExpr(ref isFirstType);
+ EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
EmitBindLogicFromString(
(ParsableFromStringSpec)type.EffectiveType,
@@ -165,51 +152,48 @@ private void EmitGetValueCoreMethod()
useIncrementalStringValueIdentifier: false);
EmitEndBlock();
- _writer.WriteLine();
}
+ _writer.WriteLine();
_writer.WriteLine("return null;");
EmitEndBlock();
_emitBlankLineBeforeNextStatement = true;
}
- private void EmitBindCoreUntypedMethod()
+ private void EmitBindCoreMainMethod()
{
- if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(MethodsToGen_CoreBindingHelper.BindCoreUntyped, out HashSet? targetTypes))
+ if (!_sourceGenSpec.TypesForGen_CoreBindingHelper_Methods.TryGetValue(MethodsToGen_CoreBindingHelper.BindCoreMain, out HashSet? targetTypes))
{
return;
}
EmitBlankLineIfRequired();
-
- EmitStartBlock($"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped)}(this {Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.obj}, Type {Identifier.type}, {MinimalDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
-
+ EmitStartBlock($"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}({Identifier.IConfiguration} {Identifier.configuration}, object {Identifier.obj}, Type {Identifier.type}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions})");
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
-
+ EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
+ EmitIConfigurationHasValueOrChildrenCheck(voidReturn: true);
_writer.WriteLine($"{Identifier.BinderOptions}? {Identifier.binderOptions} = {Identifier.GetBinderOptions}({Identifier.configureOptions});");
_writer.WriteLine();
- EmitIConfigurationHasValueOrChildrenCheck(voidReturn: true);
-
+ bool isFirstType = true;
foreach (TypeSpec type in targetTypes)
{
- EmitStartBlock($"if (type == typeof({type.MinimalDisplayString}))");
-
TypeSpec effectiveType = type.EffectiveType;
+ string conditionKindExpr = GetConditionKindExpr(ref isFirstType);
+
+ EmitStartBlock($"{conditionKindExpr} ({Identifier.type} == typeof({type.DisplayString}))");
if (!EmitInitException(effectiveType))
{
- _writer.WriteLine($"var {Identifier.temp} = ({effectiveType.MinimalDisplayString}){Identifier.obj};");
+ _writer.WriteLine($"var {Identifier.temp} = ({effectiveType.DisplayString}){Identifier.obj};");
EmitBindCoreCall(type, Identifier.temp, Identifier.configuration, InitializationKind.None);
_writer.WriteLine($"return;");
}
-
EmitEndBlock();
- _writer.WriteLine();
}
+ _writer.WriteLine();
Emit_NotSupportedException_TypeNotDetectedAsInput();
EmitEndBlock();
- _emitBlankLineBeforeNextStatement = true;
}
private void EmitBindCoreMethods()
@@ -231,11 +215,9 @@ private void EmitBindCoreMethod(TypeSpec type)
{
Debug.Assert(type.CanInitialize);
- string objParameterExpression = $"ref {type.MinimalDisplayString} {Identifier.obj}";
+ string objParameterExpression = $"ref {type.DisplayString} {Identifier.obj}";
EmitStartBlock(@$"public static void {nameof(MethodsToGen_CoreBindingHelper.BindCore)}({Identifier.IConfiguration} {Identifier.configuration}, {objParameterExpression}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
- EmitCheckForNullArgument_WithBlankLine_IfRequired(type.IsValueType);
-
TypeSpec effectiveType = type.EffectiveType;
if (effectiveType is EnumerableSpec enumerable)
{
@@ -281,9 +263,9 @@ private void EmitInitializeMethod(ObjectSpec type)
List ctorParams = type.ConstructorParameters;
IEnumerable initOnlyProps = type.Properties.Values.Where(prop => prop is { SetOnInit: true });
List ctorArgList = new();
- string displayString = type.MinimalDisplayString;
+ string displayString = type.DisplayString;
- EmitStartBlock($"public static {type.MinimalDisplayString} {GetInitalizeMethodDisplayString(type)}({Identifier.IConfiguration} {Identifier.configuration}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
+ EmitStartBlock($"public static {type.DisplayString} {GetInitalizeMethodDisplayString(type)}({Identifier.IConfiguration} {Identifier.configuration}, {Identifier.BinderOptions}? {Identifier.binderOptions})");
_emitBlankLineBeforeNextStatement = false;
foreach (ParameterSpec parameter in ctorParams)
@@ -335,7 +317,7 @@ void EmitBindImplForMember(MemberSpec member)
TypeSpec memberType = member.Type;
bool errorOnFailedBinding = member.ErrorOnFailedBinding;
- string parsedMemberIdentifierDeclarationPrefix = $"{memberType.MinimalDisplayString} {member.Name}";
+ string parsedMemberIdentifierDeclarationPrefix = $"{memberType.DisplayString} {member.Name}";
string parsedMemberIdentifier;
if (memberType is ParsableFromStringSpec { StringParsableTypeKind: StringParsableTypeKind.AssignFromSectionValue })
@@ -344,7 +326,7 @@ void EmitBindImplForMember(MemberSpec member)
if (errorOnFailedBinding)
{
- string condition = $@" if ({Identifier.configuration}[""{member.ConfigurationKeyName}""] is not {memberType.MinimalDisplayString} {member.Name})";
+ string condition = $@" if ({Identifier.configuration}[""{member.ConfigurationKeyName}""] is not {memberType.DisplayString} {member.Name})";
EmitThrowBlock(condition);
_writer.WriteLine();
return;
@@ -393,40 +375,42 @@ void EmitThrowBlock(string condition) =>
_writer.WriteLine($$"""
{{condition}}
{
- throw new {{GetInvalidOperationDisplayName()}}("{{string.Format(ExceptionMessages.ParameterHasNoMatchingConfig, type.Name, member.Name)}}");
+ throw new {{Identifier.InvalidOperationException}}("{{string.Format(ExceptionMessages.ParameterHasNoMatchingConfig, type.Name, member.Name)}}");
}
""");
}
}
+
private void EmitHelperMethods()
{
+ // Emitted if we are to bind objects with complex members, or if we're emitting BindCoreMain or GetCore methods.
+ bool emitAsConfigWithChildren = ShouldEmitMethods(MethodsToGen_CoreBindingHelper.AsConfigWithChildren);
+
if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCore))
{
+ EmitBlankLineIfRequired();
EmitValidateConfigurationKeysMethod();
}
- if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCoreUntyped | MethodsToGen_CoreBindingHelper.GetCore))
+ if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCoreMain | MethodsToGen_CoreBindingHelper.GetCore))
{
- _writer.WriteLine();
+ // HasValueOrChildren references this method.
+ Debug.Assert(emitAsConfigWithChildren);
+ EmitBlankLineIfRequired();
EmitHasValueOrChildrenMethod();
- _writer.WriteLine();
- EmitAsConfigWithChildrenMethod();
- _emitBlankLineBeforeNextStatement = true;
}
- else if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.AsConfigWithChildren))
+
+ if (emitAsConfigWithChildren)
{
- _writer.WriteLine();
+ EmitBlankLineIfRequired();
EmitAsConfigWithChildrenMethod();
- _emitBlankLineBeforeNextStatement = true;
}
- if (ShouldEmitMethods(
- MethodsToGen_CoreBindingHelper.BindCoreUntyped | MethodsToGen_CoreBindingHelper.GetCore) ||
+ if (ShouldEmitMethods(MethodsToGen_CoreBindingHelper.BindCoreMain | MethodsToGen_CoreBindingHelper.GetCore) ||
ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions))
{
- _writer.WriteLine();
+ EmitBlankLineIfRequired();
EmitGetBinderOptionsHelper();
- _emitBlankLineBeforeNextStatement = true;
}
bool enumTypeExists = false;
@@ -458,17 +442,17 @@ private void EmitValidateConfigurationKeysMethod()
EmitBlankLineIfRequired();
_writer.WriteLine($$"""
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
- public static void {{Identifier.ValidateConfigurationKeys}}(Type {{Identifier.type}}, {{MinimalDisplayString.LazyHashSetOfString}} {{keysIdentifier}}, {{Identifier.IConfiguration}} {{Identifier.configuration}}, {{Identifier.BinderOptions}}? {{Identifier.binderOptions}})
+ public static void {{Identifier.ValidateConfigurationKeys}}(Type {{Identifier.type}}, {{TypeDisplayString.LazyHashSetOfString}} {{keysIdentifier}}, {{Identifier.IConfiguration}} {{Identifier.configuration}}, {{Identifier.BinderOptions}}? {{Identifier.binderOptions}})
{
if ({{Identifier.binderOptions}}?.{{Identifier.ErrorOnUnknownConfiguration}} is true)
{
- {{MinimalDisplayString.ListOfString}}? {{Identifier.temp}} = null;
+ {{TypeDisplayString.ListOfString}}? {{Identifier.temp}} = null;
foreach ({{Identifier.IConfigurationSection}} {{Identifier.section}} in {{Identifier.configuration}}.{{Identifier.GetChildren}}())
{
if (!{{keysIdentifier}}.Value.Contains({{Expression.sectionKey}}))
{
- ({{Identifier.temp}} ??= new {{MinimalDisplayString.ListOfString}}()).Add($"'{{{Expression.sectionKey}}}'");
+ ({{Identifier.temp}} ??= new {{TypeDisplayString.ListOfString}}()).Add($"'{{{Expression.sectionKey}}}'");
}
}
@@ -490,7 +474,7 @@ private void EmitHasValueOrChildrenMethod()
{
return true;
}
- return {{Identifier.AsConfigWithChildren}}({{Identifier.configuration}}) is not null;
+ return {{MethodsToGen_CoreBindingHelper.AsConfigWithChildren}}({{Identifier.configuration}}) is not null;
}
""");
}
@@ -498,7 +482,7 @@ private void EmitHasValueOrChildrenMethod()
private void EmitAsConfigWithChildrenMethod()
{
_writer.WriteLine($$"""
- public static {{Identifier.IConfiguration}}? {{Identifier.AsConfigWithChildren}}({{Identifier.IConfiguration}} {{Identifier.configuration}})
+ public static {{Identifier.IConfiguration}}? {{MethodsToGen_CoreBindingHelper.AsConfigWithChildren}}({{Identifier.IConfiguration}} {{Identifier.configuration}})
{
foreach ({{Identifier.IConfigurationSection}} _ in {{Identifier.configuration}}.{{Identifier.GetChildren}}())
{
@@ -512,7 +496,7 @@ private void EmitAsConfigWithChildrenMethod()
private void EmitGetBinderOptionsHelper()
{
_writer.WriteLine($$"""
- public static {{Identifier.BinderOptions}}? {{Identifier.GetBinderOptions}}({{MinimalDisplayString.NullableActionOfBinderOptions}} {{Identifier.configureOptions}})
+ public static {{Identifier.BinderOptions}}? {{Identifier.GetBinderOptions}}({{TypeDisplayString.NullableActionOfBinderOptions}} {{Identifier.configureOptions}})
{
if ({{Identifier.configureOptions}} is null)
{
@@ -524,7 +508,7 @@ private void EmitGetBinderOptionsHelper()
if ({{Identifier.binderOptions}}.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"{{string.Format(ExceptionMessages.CannotSpecifyBindNonPublicProperties)}}");
+ throw new NotSupportedException($"{{string.Format(ExceptionMessages.CannotSpecifyBindNonPublicProperties)}}");
}
return {{Identifier.binderOptions}};
@@ -534,7 +518,6 @@ private void EmitGetBinderOptionsHelper()
private void EmitEnumParseMethod()
{
- string innerExceptionTypeDisplayString = _useFullyQualifiedNames ? "global::System.Exception" : "Exception";
string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.getPath}()}}", $"{{typeof(T)}}");
_writer.WriteLine($$"""
@@ -548,9 +531,9 @@ public static T ParseEnum(string value, Func getPath) where T : stru
return Enum.Parse(value, ignoreCase: true);
#endif
}
- catch ({{innerExceptionTypeDisplayString}} {{Identifier.exception}})
+ catch ({{Identifier.Exception}} {{Identifier.exception}})
{
- throw new {{GetInvalidOperationDisplayName()}}($"{{exceptionArg1}}", {{Identifier.exception}});
+ throw new {{Identifier.InvalidOperationException}}($"{{exceptionArg1}}", {{Identifier.exception}});
}
}
""");
@@ -558,29 +541,12 @@ public static T ParseEnum(string value, Func getPath) where T : stru
private void EmitPrimitiveParseMethod(ParsableFromStringSpec type)
{
- string innerExceptionTypeDisplayString;
- string cultureInfoTypeDisplayString;
- string numberStylesTypeDisplayString;
-
- if (_useFullyQualifiedNames)
- {
- innerExceptionTypeDisplayString = "global::System.Exception";
- cultureInfoTypeDisplayString = "global::System.Globalization.CultureInfo";
- numberStylesTypeDisplayString = "global::System.Globalization.NumberStyles";
- }
- else
- {
- innerExceptionTypeDisplayString = "Exception";
- cultureInfoTypeDisplayString = "CultureInfo";
- numberStylesTypeDisplayString = "NumberStyles";
- }
-
StringParsableTypeKind typeKind = type.StringParsableTypeKind;
- string typeDisplayString = type.MinimalDisplayString;
-
- string invariantCultureExpression = $"{cultureInfoTypeDisplayString}.InvariantCulture";
+ string typeDisplayString = type.DisplayString;
+ string invariantCultureExpression = $"{Identifier.CultureInfo}.InvariantCulture";
string parsedValueExpr;
+
switch (typeKind)
{
case StringParsableTypeKind.Enum:
@@ -592,12 +558,12 @@ private void EmitPrimitiveParseMethod(ParsableFromStringSpec type)
break;
case StringParsableTypeKind.Integer:
{
- parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {numberStylesTypeDisplayString}.Integer, {invariantCultureExpression})";
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {Identifier.NumberStyles}.Integer, {invariantCultureExpression})";
}
break;
case StringParsableTypeKind.Float:
{
- parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {numberStylesTypeDisplayString}.Float, {invariantCultureExpression})";
+ parsedValueExpr = $"{typeDisplayString}.{Identifier.Parse}({Identifier.value}, {Identifier.NumberStyles}.Float, {invariantCultureExpression})";
}
break;
case StringParsableTypeKind.Parse:
@@ -612,7 +578,7 @@ private void EmitPrimitiveParseMethod(ParsableFromStringSpec type)
break;
case StringParsableTypeKind.CultureInfo:
{
- parsedValueExpr = $"{cultureInfoTypeDisplayString}.GetCultureInfo({Identifier.value})";
+ parsedValueExpr = $"{Identifier.CultureInfo}.GetCultureInfo({Identifier.value})";
}
break;
case StringParsableTypeKind.Uri:
@@ -635,9 +601,9 @@ private void EmitPrimitiveParseMethod(ParsableFromStringSpec type)
{
return {{parsedValueExpr}};
}
- catch ({{innerExceptionTypeDisplayString}} {{Identifier.exception}})
+ catch ({{Identifier.Exception}} {{Identifier.exception}})
{
- throw new {{GetInvalidOperationDisplayName()}}($"{{exceptionArg1}}", {{Identifier.exception}});
+ throw new {{Identifier.InvalidOperationException}}($"{{exceptionArg1}}", {{Identifier.exception}});
}
""");
}
@@ -722,13 +688,13 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
if (keyType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue)
{
// Save value to local to avoid parsing twice - during look-up and during add.
- _writer.WriteLine($"{keyType.MinimalDisplayString} {Identifier.key} = {parsedKeyExpr};");
+ _writer.WriteLine($"{keyType.DisplayString} {Identifier.key} = {parsedKeyExpr};");
parsedKeyExpr = Identifier.key;
}
bool isValueType = elementType.IsValueType;
string expressionForElementIsNotNull = $"{Identifier.element} is not null";
- string elementTypeDisplayString = elementType.MinimalDisplayString + (elementType.IsValueType ? string.Empty : "?");
+ string elementTypeDisplayString = elementType.DisplayString + (elementType.IsValueType ? string.Empty : "?");
string expressionForElementExists = $"{objIdentifier}.{Identifier.TryGetValue}({parsedKeyExpr}, out {elementTypeDisplayString} {Identifier.element})";
string conditionToUseExistingElement = expressionForElementExists;
@@ -749,7 +715,7 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr)
// we need to copy its contents into a new instance & then append/bind to that.
string initExpression = collectionSpec.InitializationStrategy is InitializationStrategy.ParameterizedConstructor
- ? $"new {collectionSpec.ConcreteType.MinimalDisplayString}({Identifier.element})"
+ ? $"new {collectionSpec.ConcreteType.DisplayString}({Identifier.element})"
: $"{Identifier.element}.{collectionSpec.ToEnumerableMethodCall!}";
_writer.WriteLine($$"""
@@ -773,7 +739,7 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
Debug.Assert(type.NeedsMemberBinding);
string keyCacheFieldName = GetConfigKeyCacheFieldName(type);
- string validateMethodCallExpr = $"{Identifier.ValidateConfigurationKeys}(typeof({type.MinimalDisplayString}), {keyCacheFieldName}, {Identifier.configuration}, {Identifier.binderOptions});";
+ string validateMethodCallExpr = $"{Identifier.ValidateConfigurationKeys}(typeof({type.DisplayString}), {keyCacheFieldName}, {Identifier.configuration}, {Identifier.binderOptions});";
_writer.WriteLine(validateMethodCallExpr);
foreach (PropertySpec property in type.Properties.Values)
@@ -781,7 +747,7 @@ private void EmitBindCoreImplForObject(ObjectSpec type)
bool noSetter_And_IsReadonly = !property.CanSet && property.Type is CollectionSpec { InitializationStrategy: InitializationStrategy.ParameterizedConstructor };
if (property.ShouldBind() && !noSetter_And_IsReadonly)
{
- string containingTypeRef = property.IsStatic ? type.MinimalDisplayString : Identifier.obj;
+ string containingTypeRef = property.IsStatic ? type.DisplayString : Identifier.obj;
EmitBindImplForMember(
property,
memberAccessExpr: $"{containingTypeRef}.{property.Name}",
@@ -832,7 +798,7 @@ private bool EmitBindImplForMember(
return true;
}
- string sectionValidationCall = $"{Identifier.AsConfigWithChildren}({sectionParseExpr})";
+ string sectionValidationCall = $"{MethodsToGen_CoreBindingHelper.AsConfigWithChildren}({sectionParseExpr})";
string sectionIdentifier = GetIncrementalIdentifier(Identifier.section);
EmitStartBlock($"if ({sectionValidationCall} is {Identifier.IConfigurationSection} {sectionIdentifier})");
@@ -869,14 +835,14 @@ private void EmitBindCoreCallForMember(
}
Debug.Assert(canSet);
- string effectiveMemberTypeDisplayString = effectiveMemberType.MinimalDisplayString;
+ string effectiveMemberTypeDisplayString = effectiveMemberType.DisplayString;
initKind = InitializationKind.None;
if (memberType.SpecKind is TypeSpecKind.Nullable)
{
string nullableTempIdentifier = GetIncrementalIdentifier(Identifier.temp);
- _writer.WriteLine($"{memberType.MinimalDisplayString} {nullableTempIdentifier} = {memberAccessExpr};");
+ _writer.WriteLine($"{memberType.DisplayString} {nullableTempIdentifier} = {memberAccessExpr};");
_writer.WriteLine(
$"{effectiveMemberTypeDisplayString} {tempIdentifier} = {nullableTempIdentifier}.{Identifier.HasValue} ? {nullableTempIdentifier}.{Identifier.Value} : new {effectiveMemberTypeDisplayString}();");
@@ -924,7 +890,7 @@ private void EmitCollectionCastIfRequired(CollectionSpec type, out string objIde
{
objIdentifier = Identifier.temp;
_writer.WriteLine($$"""
- if ({{Identifier.obj}} is not {{type.PopulationCastType!.MinimalDisplayString}} {{objIdentifier}})
+ if ({{Identifier.obj}} is not {{type.PopulationCastType!.DisplayString}} {{objIdentifier}})
{
return;
}
@@ -936,20 +902,31 @@ private void EmitCollectionCastIfRequired(CollectionSpec type, out string objIde
private void Emit_Foreach_Section_In_ConfigChildren_StartBlock() =>
EmitStartBlock($"foreach ({Identifier.IConfigurationSection} {Identifier.section} in {Identifier.configuration}.{Identifier.GetChildren}())");
+ private void Emit_NotSupportedException_TypeNotDetectedAsInput() =>
+ _writer.WriteLine(@$"throw new NotSupportedException($""{string.Format(ExceptionMessages.TypeNotDetectedAsInput, "{type}")}"");");
+
private static string GetSectionPathFromConfigurationExpression(string configurationKeyName)
=> $@"{GetSectionFromConfigurationExpression(configurationKeyName)}.{Identifier.Path}";
private static string GetSectionFromConfigurationExpression(string configurationKeyName, bool addQuotes = true)
{
string argExpr = addQuotes ? $@"""{configurationKeyName}""" : configurationKeyName;
- return $@"{Expression.configurationGetSection}({argExpr})";
+ return $@"{Identifier.configuration}.{Identifier.GetSection}({argExpr})";
}
- private static string GetConfigKeyCacheFieldName(ObjectSpec type) =>
- $"s_configKeys_{type.DisplayStringWithoutSpecialCharacters}";
+ private static string GetConditionKindExpr(ref bool isFirstType)
+ {
+ if (isFirstType)
+ {
+ isFirstType = false;
+ return "if";
+ }
- private void Emit_NotSupportedException_TypeNotDetectedAsInput() =>
- _writer.WriteLine(@$"throw new global::System.NotSupportedException($""{string.Format(ExceptionMessages.TypeNotDetectedAsInput, "{type}")}"");");
+ return "else if";
+ }
+
+ private static string GetConfigKeyCacheFieldName(ObjectSpec type) =>
+ $"s_configKeys_{type.DisplayString.ToIdentifierSubstring()}";
}
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/Helpers.cs
index e0e6a36aabaa7c..bad56b7ce3275a 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/Helpers.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/Helpers.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
@@ -10,7 +12,9 @@ public sealed partial class ConfigurationBindingGenerator
{
private sealed partial class Emitter
{
- private static readonly AssemblyName s_assemblyName = typeof(Emitter).Assembly.GetName();
+ private string? _emittedExtsTargetType;
+
+ internal static readonly AssemblyName s_assemblyName = typeof(ConfigurationBindingGenerator).Assembly.GetName();
private enum InitializationKind
{
@@ -26,29 +30,13 @@ private static class Expression
public const string sectionPath = "section.Path";
public const string sectionValue = "section.Value";
- public const string GetBinderOptions = $"{FullyQualifiedDisplayString.CoreBindingHelper}.{Identifier.GetBinderOptions}";
- }
-
- private static class FullyQualifiedDisplayString
- {
- public const string ActionOfBinderOptions = $"global::System.Action";
- public const string AddSingleton = $"{ServiceCollectionServiceExtensions}.AddSingleton";
- public const string ConfigurationChangeTokenSource = "global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource";
- public const string CoreBindingHelper = $"global::{ProjectName}.{Identifier.CoreBindingHelper}";
- public const string IConfiguration = "global::Microsoft.Extensions.Configuration.IConfiguration";
- public const string IConfigurationSection = IConfiguration + "Section";
- public const string IOptionsChangeTokenSource = "global::Microsoft.Extensions.Options.IOptionsChangeTokenSource";
- public const string InvalidOperationException = "global::System.InvalidOperationException";
- public const string IServiceCollection = "global::Microsoft.Extensions.DependencyInjection.IServiceCollection";
- public const string NotSupportedException = "global::System.NotSupportedException";
- public const string OptionsBuilderOfTOptions = $"global::Microsoft.Extensions.Options.OptionsBuilder<{Identifier.TOptions}>";
- public const string ServiceCollectionServiceExtensions = "global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions";
- public const string Type = $"global::System.Type";
+ public static string GeneratedCodeAnnotation = $@"[GeneratedCode(""{s_assemblyName.Name}"", ""{s_assemblyName.Version}"")]";
}
- private static class MinimalDisplayString
+ private static class TypeDisplayString
{
public const string NullableActionOfBinderOptions = "Action?";
+ public const string OptionsBuilderOfTOptions = $"OptionsBuilder<{Identifier.TOptions}>";
public const string HashSetOfString = "HashSet";
public const string LazyHashSetOfString = "Lazy>";
public const string ListOfString = "List";
@@ -75,6 +63,7 @@ private static class Identifier
public const string services = nameof(services);
public const string temp = nameof(temp);
public const string type = nameof(type);
+ public const string typedObj = nameof(typedObj);
public const string validateKeys = nameof(validateKeys);
public const string value = nameof(value);
@@ -82,21 +71,19 @@ private static class Identifier
public const string AddSingleton = nameof(AddSingleton);
public const string Any = nameof(Any);
public const string Array = nameof(Array);
- public const string AsConfigWithChildren = nameof(AsConfigWithChildren);
public const string Bind = nameof(Bind);
public const string BinderOptions = nameof(BinderOptions);
+ public const string BindingExtensions = nameof(BindingExtensions);
+ public const string ConfigurationChangeTokenSource = nameof(ConfigurationChangeTokenSource);
public const string Configure = nameof(Configure);
public const string CopyTo = nameof(CopyTo);
public const string ContainsKey = nameof(ContainsKey);
- public const string CoreBindingHelper = nameof(CoreBindingHelper);
public const string Count = nameof(Count);
public const string CultureInfo = nameof(CultureInfo);
public const string CultureNotFoundException = nameof(CultureNotFoundException);
public const string Enum = nameof(Enum);
public const string ErrorOnUnknownConfiguration = nameof(ErrorOnUnknownConfiguration);
- public const string GeneratedConfigurationBinder = nameof(GeneratedConfigurationBinder);
- public const string GeneratedOptionsBuilderBinder = nameof(GeneratedOptionsBuilderBinder);
- public const string GeneratedServiceCollectionBinder = nameof(GeneratedServiceCollectionBinder);
+ public const string Exception = nameof(Exception);
public const string Get = nameof(Get);
public const string GetBinderOptions = nameof(GetBinderOptions);
public const string GetChildren = nameof(GetChildren);
@@ -108,9 +95,13 @@ private static class Identifier
public const string IConfiguration = nameof(IConfiguration);
public const string IConfigurationSection = nameof(IConfigurationSection);
public const string Int32 = "int";
+ public const string InterceptsLocation = nameof(InterceptsLocation);
public const string InvalidOperationException = nameof(InvalidOperationException);
public const string InvariantCulture = nameof(InvariantCulture);
+ public const string IOptionsChangeTokenSource = nameof(IOptionsChangeTokenSource);
+ public const string IServiceCollection = nameof(IServiceCollection);
public const string Length = nameof(Length);
+ public const string NumberStyles = nameof(NumberStyles);
public const string Parse = nameof(Parse);
public const string Path = nameof(Path);
public const string Resize = nameof(Resize);
@@ -118,17 +109,66 @@ private static class Identifier
public const string TOptions = nameof(TOptions);
public const string TryCreate = nameof(TryCreate);
public const string TryGetValue = nameof(TryGetValue);
- public const string TryParse = nameof(TryParse);
+ public const string Type = nameof(Type);
public const string Uri = nameof(Uri);
public const string ValidateConfigurationKeys = nameof(ValidateConfigurationKeys);
public const string Value = nameof(Value);
}
- private bool ShouldEmitBinders() =>
+ private bool ShouldEmitBindingExtensions() =>
ShouldEmitMethods(MethodsToGen_ConfigurationBinder.Any) ||
ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder.Any) ||
ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Any);
+ private void EmitInterceptsLocationAnnotations(Enum generatedBindingOverload)
+ {
+ // The only time a generated binding method won't have any locations to
+ // intercept is when either of these methods are used as helpers for
+ // other generated OptionsBuilder or ServiceCollection binding extensions.
+ bool interceptsCalls = _sourceGenSpec.InterceptionInfo.TryGetValue(generatedBindingOverload, out List? infoList);
+ Debug.Assert(interceptsCalls ||
+ generatedBindingOverload is MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions ||
+ generatedBindingOverload is MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions);
+
+ if (interceptsCalls)
+ {
+ EmitInterceptsLocationAnnotations(infoList);
+ }
+ }
+
+ private void EmitInterceptsLocationAnnotations(List infoList)
+ {
+ foreach (InterceptorLocationInfo info in infoList)
+ {
+ _writer.WriteLine($@"[{Identifier.InterceptsLocation}Attribute(@""{info.FilePath}"", {info.LineNumber}, {info.CharacterNumber})]");
+ }
+ }
+
+ private void EmitBindingExtStartRegion(string targetType)
+ {
+ Debug.Assert(_emittedExtsTargetType is null);
+
+ EmitBlankLineIfRequired();
+ _emittedExtsTargetType = targetType;
+ EmitBindingExtRegionText(isStart: true);
+ _emitBlankLineBeforeNextStatement = false;
+ }
+
+ private void EmitBindingExtEndRegion()
+ {
+ Debug.Assert(_emittedExtsTargetType is not null);
+
+ EmitBindingExtRegionText(isStart: false);
+ _emittedExtsTargetType = null;
+ _emitBlankLineBeforeNextStatement = true;
+ }
+
+ private void EmitBindingExtRegionText(bool isStart)
+ {
+ string endSource = isStart ? string.Empty : "end";
+ _writer.WriteLine($"#{endSource}region {_emittedExtsTargetType} extensions.");
+ }
+
///
/// Starts a block of source code.
///
@@ -171,24 +211,12 @@ private void EmitBlankLineIfRequired()
_emitBlankLineBeforeNextStatement = true;
}
- private void EmitCheckForNullArgument_WithBlankLine_IfRequired(bool isValueType)
- {
- if (!isValueType)
- {
- EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
- }
- }
-
private void EmitCheckForNullArgument_WithBlankLine(string paramName)
{
- string exceptionTypeDisplayString = _useFullyQualifiedNames
- ? "global::System.ArgumentNullException"
- : "ArgumentNullException";
-
_writer.WriteLine($$"""
if ({{paramName}} is null)
{
- throw new {{exceptionTypeDisplayString}}(nameof({{paramName}}));
+ throw new ArgumentNullException(nameof({{paramName}}));
}
""");
@@ -201,51 +229,28 @@ private bool EmitInitException(TypeSpec type)
if (!type.CanInitialize)
{
- _writer.WriteLine(GetInitException(type.InitExceptionMessage) + ";");
+ _writer.WriteLine($@"throw new {Identifier.InvalidOperationException}(""{type.InitExceptionMessage}"");");
return true;
}
return false;
}
- private void EmitRootBindingClassStartBlock(string className)
- {
- EmitBlankLineIfRequired();
- EmitStartBlock($$"""
- /// Generated helper providing an AOT and linking compatible implementation for configuration binding.
- {{GetGeneratedCodeAttributeSrc()}}
- internal static class {{className}}
- """);
-
- _emitBlankLineBeforeNextStatement = false;
- }
-
- private string GetGeneratedCodeAttributeSrc()
- {
- string attributeRefExpr = _useFullyQualifiedNames ? $"global::System.CodeDom.Compiler.GeneratedCodeAttribute" : "GeneratedCode";
- return $@"[{attributeRefExpr}(""{s_assemblyName.Name}"", ""{s_assemblyName.Version}"")]";
- }
-
- private string GetInitException(string message) => $@"throw new {GetInvalidOperationDisplayName()}(""{message}"")";
-
private string GetIncrementalIdentifier(string prefix) => $"{prefix}{_valueSuffixIndex++}";
- private string GetInitalizeMethodDisplayString(ObjectSpec type) =>
- GetHelperMethodDisplayString($"{nameof(MethodsToGen_CoreBindingHelper.Initialize)}{type.DisplayStringWithoutSpecialCharacters}");
-
- private string GetTypeDisplayString(TypeSpec type) => _useFullyQualifiedNames ? type.FullyQualifiedDisplayString : type.MinimalDisplayString;
-
- private string GetHelperMethodDisplayString(string methodName)
- {
- if (_useFullyQualifiedNames)
- {
- methodName = FullyQualifiedDisplayString.CoreBindingHelper + "." + methodName;
- }
-
- return methodName;
- }
-
- private string GetInvalidOperationDisplayName() => _useFullyQualifiedNames ? FullyQualifiedDisplayString.InvalidOperationException : Identifier.InvalidOperationException;
+ private static string GetInitalizeMethodDisplayString(ObjectSpec type) =>
+ $"{nameof(MethodsToGen_CoreBindingHelper.Initialize)}{type.DisplayString.ToIdentifierSubstring()}";
}
}
+
+ internal static class EmitterExtensions
+ {
+ public static string ToIdentifierSubstring(this string typeDisplayName) =>
+ typeDisplayName
+ .Replace("[]", nameof(Array))
+ .Replace(", ", string.Empty)
+ .Replace(".", string.Empty)
+ .Replace("<", string.Empty)
+ .Replace(">", string.Empty);
+ }
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsBuilderConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsBuilderConfigurationExtensions.cs
index 71d0b6989dd970..d49198196fd491 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsBuilderConfigurationExtensions.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsBuilderConfigurationExtensions.cs
@@ -9,19 +9,17 @@ private sealed partial class Emitter
{
private bool ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder methods) => (_sourceGenSpec.MethodsToGen_OptionsBuilderExt & methods) != 0;
- private void EmitBinder_Extensions_OptionsBuilder()
+ private void EmitBindingExtensions_OptionsBuilder()
{
if (!ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder.Any))
{
return;
}
- EmitRootBindingClassStartBlock(Identifier.GeneratedOptionsBuilderBinder);
-
+ EmitBindingExtStartRegion(TypeDisplayString.OptionsBuilderOfTOptions);
EmitBindMethods_Extensions_OptionsBuilder();
EmitBindConfigurationMethod();
-
- EmitEndBlock();
+ EmitBindingExtEndRegion();
}
private void EmitBindMethods_Extensions_OptionsBuilder()
@@ -32,24 +30,25 @@ private void EmitBindMethods_Extensions_OptionsBuilder()
}
const string documentation = @"/// Registers a configuration instance which will bind against.";
- const string paramList = $"{FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}";
+ const string paramList = $"{Identifier.IConfiguration} {Identifier.configuration}";
if (ShouldEmitMethods(MethodsToGen_Extensions_OptionsBuilder.Bind_T))
{
- EmitMethodStartBlock("Bind", paramList, documentation);
- _writer.WriteLine($"return global::{Identifier.GeneratedOptionsBuilderBinder}.Bind({Identifier.optionsBuilder}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
+ EmitMethodStartBlock(MethodsToGen_Extensions_OptionsBuilder.Bind_T, "Bind", paramList, documentation);
+ _writer.WriteLine($"return Bind({Identifier.optionsBuilder}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
EmitEndBlock();
}
EmitMethodStartBlock(
+ MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions,
"Bind",
- paramList + $", {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}",
+ paramList + $", {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}",
documentation);
EmitCheckForNullArgument_WithBlankLine(Identifier.optionsBuilder);
_writer.WriteLine($$"""
- global::{{Identifier.GeneratedServiceCollectionBinder}}.{{Identifier.Configure}}<{{Identifier.TOptions}}>({{Identifier.optionsBuilder}}.{{Identifier.Services}}, {{Identifier.optionsBuilder}}.Name, {{Identifier.configuration}}, {{Identifier.configureOptions}});
+ {{Identifier.Configure}}<{{Identifier.TOptions}}>({{Identifier.optionsBuilder}}.{{Identifier.Services}}, {{Identifier.optionsBuilder}}.Name, {{Identifier.configuration}}, {{Identifier.configureOptions}});
return {{Identifier.optionsBuilder}};
""");
@@ -63,19 +62,20 @@ private void EmitBindConfigurationMethod()
return;
}
- const string documentation = $@"/// Registers the dependency injection container to bind against the obtained from the DI service provider.";
- string paramList = $"string {Identifier.configSectionPath}, {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions} = null";
+ const string documentation = $@"/// Registers the dependency injection container to bind against the obtained from the DI service provider.";
+ string paramList = $"string {Identifier.configSectionPath}, {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions} = null";
- EmitMethodStartBlock("BindConfiguration", paramList, documentation);
+ EmitMethodStartBlock(MethodsToGen_Extensions_OptionsBuilder.BindConfiguration, "BindConfiguration", paramList, documentation);
EmitCheckForNullArgument_WithBlankLine(Identifier.optionsBuilder);
EmitCheckForNullArgument_WithBlankLine(Identifier.configSectionPath);
- EmitStartBlock($"{Identifier.optionsBuilder}.{Identifier.Configure}<{FullyQualifiedDisplayString.IConfiguration}>(({Identifier.obj}, {Identifier.configuration}) =>");
-
+ EmitStartBlock($"{Identifier.optionsBuilder}.{Identifier.Configure}<{Identifier.IConfiguration}>(({Identifier.obj}, {Identifier.configuration}) =>");
+ EmitCheckForNullArgument_WithBlankLine(Identifier.obj);
+ EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
_writer.WriteLine($$"""
- {{FullyQualifiedDisplayString.IConfiguration}} {{Identifier.section}} = string.Equals(string.Empty, {{Identifier.configSectionPath}}, global::System.StringComparison.OrdinalIgnoreCase) ? {{Identifier.configuration}} : {{Identifier.configuration}}.{{Identifier.GetSection}}({{Identifier.configSectionPath}});
- {{FullyQualifiedDisplayString.CoreBindingHelper}}.{{nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped)}}({{Identifier.section}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}});
+ {{Identifier.IConfiguration}} {{Identifier.section}} = string.Equals(string.Empty, {{Identifier.configSectionPath}}, StringComparison.OrdinalIgnoreCase) ? {{Identifier.configuration}} : {{Identifier.configuration}}.{{Identifier.GetSection}}({{Identifier.configSectionPath}});
+ {{nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}}({{Identifier.section}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}});
""");
EmitEndBlock(endBraceTrailingSource: ");");
@@ -83,20 +83,20 @@ private void EmitBindConfigurationMethod()
_writer.WriteLine();
_writer.WriteLine($$"""
- {{FullyQualifiedDisplayString.AddSingleton}}<{{FullyQualifiedDisplayString.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>, {{FullyQualifiedDisplayString.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>>({{Identifier.optionsBuilder}}.{{Identifier.Services}});
+ {{Identifier.optionsBuilder}}.{{Identifier.Services}}.{{Identifier.AddSingleton}}<{{Identifier.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>, {{Identifier.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>>();
return {{Identifier.optionsBuilder}};
""");
EmitEndBlock();
}
- private void EmitMethodStartBlock(string methodName, string paramList, string documentation)
+ private void EmitMethodStartBlock(MethodsToGen_Extensions_OptionsBuilder method, string methodName, string paramList, string documentation)
{
- paramList = $"this {FullyQualifiedDisplayString.OptionsBuilderOfTOptions} {Identifier.optionsBuilder}, {paramList}";
-
+ paramList = $"this {TypeDisplayString.OptionsBuilderOfTOptions} {Identifier.optionsBuilder}, {paramList}";
EmitBlankLineIfRequired();
_writer.WriteLine(documentation);
- EmitStartBlock($"public static {FullyQualifiedDisplayString.OptionsBuilderOfTOptions} {methodName}<{Identifier.TOptions}>({paramList}) where {Identifier.TOptions} : class");
+ EmitInterceptsLocationAnnotations(method);
+ EmitStartBlock($"public static {TypeDisplayString.OptionsBuilderOfTOptions} {methodName}<{Identifier.TOptions}>({paramList}) where {Identifier.TOptions} : class");
}
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsConfigurationServiceCollectionExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsConfigurationServiceCollectionExtensions.cs
index f4cd4800df1230..0348eb5047e970 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsConfigurationServiceCollectionExtensions.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/OptionsConfigurationServiceCollectionExtensions.cs
@@ -9,71 +9,72 @@ private sealed partial class Emitter
{
private bool ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection methods) => (_sourceGenSpec.MethodsToGen_ServiceCollectionExt & methods) != 0;
- private void EmitBinder_Extensions_IServiceCollection()
+ private void EmitBindingExtensions_IServiceCollection()
{
if (!ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Any))
{
return;
}
- EmitRootBindingClassStartBlock(Identifier.GeneratedServiceCollectionBinder);
+ EmitBindingExtStartRegion(Identifier.IServiceCollection);
+ EmitConfigureMethods();
+ EmitBindingExtEndRegion();
+ }
+ private void EmitConfigureMethods()
+ {
const string defaultNameExpr = "string.Empty";
- const string configureMethodString = $"global::{Identifier.GeneratedServiceCollectionBinder}.{Identifier.Configure}";
- string configParam = $"{FullyQualifiedDisplayString.IConfiguration} {Identifier.configuration}";
+ string configParam = $"{Identifier.IConfiguration} {Identifier.configuration}";
if (ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Configure_T))
{
- EmitStartMethod(configParam);
- _writer.WriteLine($"return {configureMethodString}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
+ EmitStartMethod(MethodsToGen_Extensions_ServiceCollection.Configure_T, configParam);
+ _writer.WriteLine($"return {Identifier.Configure}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
EmitEndBlock();
}
if (ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Configure_T_name))
{
EmitStartMethod(
+ MethodsToGen_Extensions_ServiceCollection.Configure_T_name,
paramList: $"string? {Identifier.name}, " + configParam);
- _writer.WriteLine($"return {configureMethodString}<{Identifier.TOptions}>({Identifier.services}, {Identifier.name}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
+ _writer.WriteLine($"return {Identifier.Configure}<{Identifier.TOptions}>({Identifier.services}, {Identifier.name}, {Identifier.configuration}, {Identifier.configureOptions}: null);");
EmitEndBlock();
}
if (ShouldEmitMethods(MethodsToGen_Extensions_ServiceCollection.Configure_T_BinderOptions))
{
EmitStartMethod(
- paramList: configParam + $", {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}");
- _writer.WriteLine($"return {configureMethodString}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions});");
+ MethodsToGen_Extensions_ServiceCollection.Configure_T_BinderOptions,
+ paramList: configParam + $", {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}");
+ _writer.WriteLine($"return {Identifier.Configure}<{Identifier.TOptions}>({Identifier.services}, {defaultNameExpr}, {Identifier.configuration}, {Identifier.configureOptions});");
EmitEndBlock();
}
// Core Configure method that the other overloads call.
// Like the others, it is public API that could be called directly by users.
// So, it is always generated whenever a Configure overload is called.
- string optionsNamespaceName = "global::Microsoft.Extensions.Options";
- string bindCoreUntypedDisplayString = GetHelperMethodDisplayString(nameof(MethodsToGen_CoreBindingHelper.BindCoreUntyped));
+ string optionsNamespaceName = "Microsoft.Extensions.Options";
- EmitStartMethod(paramList: $"string? {Identifier.name}, " + configParam + $", {FullyQualifiedDisplayString.ActionOfBinderOptions}? {Identifier.configureOptions}");
+ EmitStartMethod(MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions, paramList: $"string? {Identifier.name}, " + configParam + $", {TypeDisplayString.NullableActionOfBinderOptions} {Identifier.configureOptions}");
EmitCheckForNullArgument_WithBlankLine(Identifier.services);
EmitCheckForNullArgument_WithBlankLine(Identifier.configuration);
_writer.WriteLine($$"""
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions({{Identifier.services}});
- {{FullyQualifiedDisplayString.AddSingleton}}<{{FullyQualifiedDisplayString.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>>({{Identifier.services}}, new {{FullyQualifiedDisplayString.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.configuration}}));
- return {{FullyQualifiedDisplayString.AddSingleton}}<{{optionsNamespaceName}}.IConfigureOptions<{{Identifier.TOptions}}>>({{Identifier.services}}, new {{optionsNamespaceName}}.ConfigureNamedOptions<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.obj}} => {{bindCoreUntypedDisplayString}}({{Identifier.configuration}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}), {{Identifier.configureOptions}})));
+ OptionsServiceCollectionExtensions.AddOptions({{Identifier.services}});
+ {{Identifier.services}}.{{Identifier.AddSingleton}}<{{Identifier.IOptionsChangeTokenSource}}<{{Identifier.TOptions}}>>(new {{Identifier.ConfigurationChangeTokenSource}}<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.configuration}}));
+ return {{Identifier.services}}.{{Identifier.AddSingleton}}<{{optionsNamespaceName}}.IConfigureOptions<{{Identifier.TOptions}}>>(new {{optionsNamespaceName}}.ConfigureNamedOptions<{{Identifier.TOptions}}>({{Identifier.name}}, {{Identifier.obj}} => {{nameof(MethodsToGen_CoreBindingHelper.BindCoreMain)}}({{Identifier.configuration}}, {{Identifier.obj}}, typeof({{Identifier.TOptions}}){{Identifier.configureOptions}})));
""");
EmitEndBlock();
-
- EmitEndBlock();
- _emitBlankLineBeforeNextStatement = true;
}
- private void EmitStartMethod(string paramList)
+ private void EmitStartMethod(MethodsToGen_Extensions_ServiceCollection overload, string paramList)
{
- paramList = $"this {FullyQualifiedDisplayString.IServiceCollection} {Identifier.services}, {paramList}";
+ paramList = $"this {Identifier.IServiceCollection} {Identifier.services}, {paramList}";
EmitBlankLineIfRequired();
- EmitStartBlock($$"""
- /// Registers a configuration instance which TOptions will bind against.
- public static {{FullyQualifiedDisplayString.IServiceCollection}} {{Identifier.Configure}}<{{Identifier.TOptions}}>({{paramList}}) where {{Identifier.TOptions}} : class
- """);
+ _writer.WriteLine("/// Registers a configuration instance which TOptions will bind against.");
+ EmitInterceptsLocationAnnotations(overload);
+ EmitStartBlock($"public static {Identifier.IServiceCollection} {Identifier.Configure}<{Identifier.TOptions}>({paramList}) where {Identifier.TOptions} : class");
}
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/InterceptorLocationInfo.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/InterceptorLocationInfo.cs
new file mode 100644
index 00000000000000..d1dc4f4afa7e7e
--- /dev/null
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/InterceptorLocationInfo.cs
@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Operations;
+using Microsoft.CodeAnalysis.Text;
+
+namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
+{
+ internal sealed record InterceptorLocationInfo
+ {
+ public InterceptorLocationInfo(IInvocationOperation operation)
+ {
+ SyntaxNode operationSyntax = operation.Syntax;
+ TextSpan operationSpan = operationSyntax.Span;
+ SyntaxTree operationSyntaxTree = operationSyntax.SyntaxTree;
+
+ FilePath = GetInterceptorFilePath(operationSyntaxTree, operation.SemanticModel?.Compilation.Options.SourceReferenceResolver);
+
+ FileLinePositionSpan span = operationSyntaxTree.GetLineSpan(operationSpan);
+ LineNumber = span.StartLinePosition.Line + 1;
+
+ // Calculate the character offset to the end of the binding invocation detected.
+ int invocationLength = ((MemberAccessExpressionSyntax)((InvocationExpressionSyntax)operationSyntax).Expression).Expression.Span.Length;
+ CharacterNumber = span.StartLinePosition.Character + invocationLength + 2;
+ }
+
+ public string FilePath { get; }
+ public int LineNumber { get; }
+ public int CharacterNumber { get; }
+
+ // Utilize the same logic used by the interceptors API for resolving the source mapped value of a path.
+ // https://github.com/dotnet/roslyn/blob/f290437fcc75dad50a38c09e0977cce13a64f5ba/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs#L1063-L1064
+ private static string GetInterceptorFilePath(SyntaxTree tree, SourceReferenceResolver? resolver) =>
+ resolver?.NormalizePath(tree.FilePath, baseFilePath: null) ?? tree.FilePath;
+ }
+
+ internal sealed record ConfigurationBinderInterceptorInfo
+ {
+ private OverloadInterceptorInfo? _bind_Instance;
+ private OverloadInterceptorInfo? _bind_instance_BinderOptions;
+ private OverloadInterceptorInfo? _bind_key_instance;
+
+ public void RegisterOverloadInfo(MethodsToGen_ConfigurationBinder overload, TypeSpec type, IInvocationOperation operation)
+ {
+ OverloadInterceptorInfo overloadInfo = DetermineOverload(overload, initIfNull: true);
+ overloadInfo.RegisterLocationInfo(type, operation);
+ }
+
+ public OverloadInterceptorInfo GetOverloadInfo(MethodsToGen_ConfigurationBinder overload) =>
+ DetermineOverload(overload, initIfNull: false) ?? throw new ArgumentNullException(nameof(overload));
+
+ private OverloadInterceptorInfo? DetermineOverload(MethodsToGen_ConfigurationBinder overload, bool initIfNull)
+ {
+ return overload switch
+ {
+ MethodsToGen_ConfigurationBinder.Bind_instance => InitIfNull(ref _bind_Instance),
+ MethodsToGen_ConfigurationBinder.Bind_instance_BinderOptions => InitIfNull(ref _bind_instance_BinderOptions),
+ MethodsToGen_ConfigurationBinder.Bind_key_instance => InitIfNull(ref _bind_key_instance),
+ _ => throw new InvalidOperationException(nameof(overload)),
+ };
+
+ OverloadInterceptorInfo InitIfNull(ref OverloadInterceptorInfo? info)
+ {
+ if (initIfNull)
+ {
+ info ??= new OverloadInterceptorInfo();
+ }
+
+ return info;
+ }
+ }
+ }
+
+ internal sealed record OverloadInterceptorInfo : IEnumerable>>
+ {
+ private readonly Dictionary> _typeInterceptionInfo = new();
+
+ public void RegisterLocationInfo(TypeSpec type, IInvocationOperation operation) =>
+ _typeInterceptionInfo.RegisterCacheEntry(type, new InterceptorLocationInfo(operation));
+
+ public IEnumerator>> GetEnumerator() => _typeInterceptionInfo.GetEnumerator();
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/MethodsToGen.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/MethodsToGen.cs
index 7b40f198e08f23..2c582b20e8ebd6 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/MethodsToGen.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/MethodsToGen.cs
@@ -10,11 +10,12 @@ public enum MethodsToGen_CoreBindingHelper
{
None = 0x0,
BindCore = 0x1,
- BindCoreUntyped = 0x2,
- GetCore = 0x4,
- GetValueCore = 0x8,
+ GetCore = 0x2,
+ GetValueCore = 0x4,
+ BindCoreMain = 0x8,
Initialize = 0x10,
- AsConfigWithChildren = 0x20,
+ HasValueOrChildren = 0x20,
+ AsConfigWithChildren = 0x40,
}
///
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/BinderInvocation.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/BinderInvocation.cs
index 554786589c8c81..ad7c4c09204d4b 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/BinderInvocation.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/BinderInvocation.cs
@@ -40,7 +40,7 @@ static bool IsCandidateBindingMethodName(string name) =>
IsValidMethodName_OptionsConfigurationServiceCollectionExtensions(name);
}
- private static bool IsBindingOperation(IInvocationOperation operation)
+ public static bool IsBindingOperation(IInvocationOperation operation)
{
if (operation.TargetMethod is not IMethodSymbol
{
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/ConfigurationBinder.cs
index a663c441c55ce3..e24ce11fe4374c 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/ConfigurationBinder.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/ConfigurationBinder.cs
@@ -102,15 +102,7 @@ private void RegisterBindInvocation(BinderInvocation invocation)
if (GetTargetTypeForRootInvocationCore(type, invocation.Location) is TypeSpec typeSpec)
{
- Dictionary> types = _sourceGenSpec.TypesForGen_ConfigurationBinder_BindMethods;
-
- if (!types.TryGetValue(overload, out HashSet? typeSpecs))
- {
- types[overload] = typeSpecs = new HashSet();
- }
-
- _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
- typeSpecs.Add(typeSpec);
+ RegisterAsInterceptor_ConfigBinder_BindMethod(overload, typeSpec, invocation.Operation);
}
static ITypeSymbol? ResolveType(IOperation conversionOperation) =>
@@ -184,8 +176,8 @@ private void RegisterGetInvocation(BinderInvocation invocation)
if (GetTargetTypeForRootInvocation(type, invocation.Location) is TypeSpec typeSpec)
{
- _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
- RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.GetCore, typeSpec);
+ RegisterAsInterceptor_ConfigBinder(overload, invocation.Operation);
+ RegisterTypeForGetCoreGen(typeSpec);
}
}
@@ -253,10 +245,27 @@ private void RegisterGetValueInvocation(BinderInvocation invocation)
if (IsParsableFromString(effectiveType, out _) &&
GetTargetTypeForRootInvocationCore(type, invocation.Location) is TypeSpec typeSpec)
{
- _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
+ RegisterAsInterceptor_ConfigBinder(overload, invocation.Operation);
RegisterTypeForMethodGen(MethodsToGen_CoreBindingHelper.GetValueCore, typeSpec);
}
}
+
+ private void RegisterAsInterceptor_ConfigBinder(MethodsToGen_ConfigurationBinder overload, IInvocationOperation operation)
+ {
+ _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
+ RegisterAsInterceptor(overload, operation);
+ }
+
+ ///
+ /// Registers generated Bind methods as interceptors. This is done differently from other root
+ /// methods because we need to
+ /// explicitly account for the type to bind, to avoid type-check issues for polymorphic objects.
+ ///
+ private void RegisterAsInterceptor_ConfigBinder_BindMethod(MethodsToGen_ConfigurationBinder overload, TypeSpec typeSpec, IInvocationOperation operation)
+ {
+ _sourceGenSpec.MethodsToGen_ConfigurationBinder |= overload;
+ _sourceGenSpec.InterceptionInfo_ConfigBinder.RegisterOverloadInfo(overload, typeSpec, operation);
+ }
}
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsBuilderConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsBuilderConfigurationExtensions.cs
index d01e80d708ca11..a62e63c0d90d5e 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsBuilderConfigurationExtensions.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsBuilderConfigurationExtensions.cs
@@ -34,9 +34,6 @@ private void RegisterMethodInvocation_OptionsBuilderExt(BinderInvocation invocat
return;
}
- // We are going to emit calls to APIs on IServiceCollection.
- _sourceGenSpec.TypeNamespaces.Add("Microsoft.Extensions.DependencyInjection");
-
if (targetMethod.Name is "Bind")
{
RegisterBindInvocation(invocation, typeSpec);
@@ -61,20 +58,19 @@ private void RegisterBindInvocation(BinderInvocation invocation, TypeSpec typeSp
return;
}
- if (paramCount is 2)
- {
- _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= MethodsToGen_Extensions_OptionsBuilder.Bind_T;
- }
- else if (paramCount is 3 && SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type))
+ MethodsToGen_Extensions_OptionsBuilder overload = paramCount switch
{
- _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions;
- }
- else
+ 2 => MethodsToGen_Extensions_OptionsBuilder.Bind_T,
+ 3 when SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type) =>
+ MethodsToGen_Extensions_OptionsBuilder.Bind_T_BinderOptions,
+ _ => MethodsToGen_Extensions_OptionsBuilder.None
+ };
+
+ if (overload is not MethodsToGen_Extensions_OptionsBuilder.None)
{
- return;
+ RegisterAsInterceptor_OptionsBuilder(overload, operation);
+ RegisterTypeForMethodGen(MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions, typeSpec);
}
-
- RegisterTypeForMethodGen(MethodsToGen_Extensions_ServiceCollection.Configure_T_name_BinderOptions, typeSpec);
}
private void ParseBindConfigurationInvocation(BinderInvocation invocation, TypeSpec typeSpec)
@@ -85,12 +81,26 @@ private void ParseBindConfigurationInvocation(BinderInvocation invocation, TypeS
int paramCount = @params.Length;
Debug.Assert(paramCount >= 2);
- if (paramCount is 3 && @params[1].Type.SpecialType is SpecialType.System_String && SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type))
+ if (paramCount is 3 &&
+ @params[1].Type.SpecialType is SpecialType.System_String &&
+ SymbolEqualityComparer.Default.Equals(_typeSymbols.ActionOfBinderOptions, @params[2].Type))
{
- _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= MethodsToGen_Extensions_OptionsBuilder.BindConfiguration_T_path_BinderOptions;
- RegisterTypeForBindCoreUntypedGen(typeSpec);
+ RegisterAsInterceptor_OptionsBuilder(MethodsToGen_Extensions_OptionsBuilder.BindConfiguration_T_path_BinderOptions, invocation.Operation);
+ RegisterTypeForBindCoreMainGen(typeSpec);
}
}
+
+ private void RegisterAsInterceptor_OptionsBuilder(MethodsToGen_Extensions_OptionsBuilder overload, IInvocationOperation operation)
+ {
+ _sourceGenSpec.MethodsToGen_OptionsBuilderExt |= overload;
+ RegisterAsInterceptor(overload, operation);
+
+ // Emitting refs to IOptionsChangeTokenSource, ConfigurationChangeTokenSource.
+ _sourceGenSpec.Namespaces.Add("Microsoft.Extensions.Options");
+
+ // Emitting refs to OptionsBuilder.
+ _sourceGenSpec.Namespaces.Add("Microsoft.Extensions.DependencyInjection");
+ }
}
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsConfigurationServiceCollectionExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsConfigurationServiceCollectionExtensions.cs
index 02c75b4ab653b3..c356b29a69efff 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsConfigurationServiceCollectionExtensions.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Parser/OptionsConfigurationServiceCollectionExtensions.cs
@@ -79,12 +79,14 @@ @params[1].Type.SpecialType is SpecialType.System_String &&
}
RegisterTypeForMethodGen(overload, typeSpec);
+ RegisterAsInterceptor(overload, operation);
}
private void RegisterTypeForMethodGen(MethodsToGen_Extensions_ServiceCollection overload, TypeSpec typeSpec)
{
_sourceGenSpec.MethodsToGen_ServiceCollectionExt |= overload;
- RegisterTypeForBindCoreUntypedGen(typeSpec);
+ _sourceGenSpec.Namespaces.Add("Microsoft.Extensions.DependencyInjection");
+ RegisterTypeForBindCoreMainGen(typeSpec);
}
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj
index 785a18c5c0978e..5b10a6f8e06c6b 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj
@@ -11,6 +11,8 @@
+
+
@@ -26,12 +28,14 @@
+
-
+
+
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ObjectSpec.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ObjectSpec.cs
index 1696ee099fe469..8cc0ba68b49381 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ObjectSpec.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ObjectSpec.cs
@@ -22,10 +22,6 @@ public ObjectSpec(INamedTypeSymbol type) : base(type) { }
public List ConstructorParameters { get; } = new();
- private string _displayStringWithoutSpecialCharacters;
- public string DisplayStringWithoutSpecialCharacters =>
- _displayStringWithoutSpecialCharacters ??= $"{MinimalDisplayString.Replace(".", string.Empty).Replace("<", string.Empty).Replace(">", string.Empty)}";
-
public override bool NeedsMemberBinding => CanInitialize &&
Properties.Values.Count > 0 &&
Properties.Values.Any(p => p.ShouldBind());
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ParsableFromStringSpec.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ParsableFromStringSpec.cs
index 6b5bb5b61ea371..e19e3e61d210f3 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ParsableFromStringSpec.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/ParsableFromStringSpec.cs
@@ -24,7 +24,7 @@ public string ParseMethodName
_parseMethodName ??= StringParsableTypeKind is StringParsableTypeKind.ByteArray
? "ParseByteArray"
// MinimalDisplayString.Length is certainly > 2.
- : $"Parse{(char.ToUpper(MinimalDisplayString[0]) + MinimalDisplayString.Substring(1)).Replace(".", "")}";
+ : $"Parse{(char.ToUpper(DisplayString[0]) + DisplayString.Substring(1)).Replace(".", "")}";
return _parseMethodName;
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/SourceGenerationSpec.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/SourceGenerationSpec.cs
index 88c4b24f57a5ea..760d57b1dcc888 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/SourceGenerationSpec.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/SourceGenerationSpec.cs
@@ -1,21 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
using System.Collections.Generic;
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
internal sealed record SourceGenerationSpec
{
+ public Dictionary> InterceptionInfo { get; } = new();
+ public ConfigurationBinderInterceptorInfo InterceptionInfo_ConfigBinder { get; } = new();
+
public Dictionary> TypesForGen_CoreBindingHelper_Methods { get; } = new();
- public Dictionary> TypesForGen_ConfigurationBinder_BindMethods { get; } = new();
public HashSet PrimitivesForHelperGen { get; } = new();
- public HashSet TypeNamespaces { get; } = new()
+ public HashSet Namespaces { get; } = new()
{
"System",
"System.CodeDom.Compiler",
"System.Globalization",
+ "System.Runtime.CompilerServices",
"Microsoft.Extensions.Configuration",
};
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/TypeSpec.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/TypeSpec.cs
index 6a6292b7ebd0b4..6f5e26bf3f6d38 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/TypeSpec.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/TypeSpec.cs
@@ -17,17 +17,14 @@ public TypeSpec(ITypeSymbol type)
{
IsValueType = type.IsValueType;
Namespace = type.ContainingNamespace?.ToDisplayString();
- FullyQualifiedDisplayString = type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
- MinimalDisplayString = type.ToDisplayString(s_minimalDisplayFormat);
- Name = Namespace + "." + MinimalDisplayString.Replace(".", "+");
+ DisplayString = type.ToDisplayString(s_minimalDisplayFormat);
+ Name = Namespace + "." + DisplayString.Replace(".", "+");
IsInterface = type.TypeKind is TypeKind.Interface;
}
public string Name { get; }
- public string FullyQualifiedDisplayString { get; }
-
- public string MinimalDisplayString { get; }
+ public string DisplayString { get; }
public string? Namespace { get; }
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx
index 301913987d7c7e..3978cbaac6ce48 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx
@@ -133,10 +133,10 @@
The collection element type is not supported: '{0}'.
- The project's language version has to be at least 'C# 11'.
+ The project's language version has to be at least 'C# 12'.
- Language version is required to be at least C# 11
+ Language version is required to be at least C# 12Cannot create instance of type '{0}' because it is missing a public instance constructor.
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf
index e248c54626865f..c6672eaff0bcd8 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- Jazyková verze projektu musí být alespoň C# 11
+ The project's language version has to be at least 'C# 12'.
+ Jazyková verze projektu musí být alespoň C# 11
- Language version is required to be at least C# 11
- Verze jazyka musí být alespoň C# 11
+ Language version is required to be at least C# 12
+ Verze jazyka musí být alespoň C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf
index 1fa847592bd02e..5f353065a5f511 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- Die Sprachversion des Projekts muss mindestens „C# 11“ sein
+ The project's language version has to be at least 'C# 12'.
+ Die Sprachversion des Projekts muss mindestens „C# 11“ sein
- Language version is required to be at least C# 11
- Die Sprachversion muss mindestens C# 11 sein
+ Language version is required to be at least C# 12
+ Die Sprachversion muss mindestens C# 11 sein
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf
index c52b2317ceaded..cd54149e66c2fa 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- La versión del lenguaje del proyecto debe ser al menos "C# 11".
+ The project's language version has to be at least 'C# 12'.
+ La versión del lenguaje del proyecto debe ser al menos "C# 11".
- Language version is required to be at least C# 11
- La versión del lenguaje debe ser al menos C# 11
+ Language version is required to be at least C# 12
+ La versión del lenguaje debe ser al menos C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf
index 19362d7336208f..b1c0753a49e8a5 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- La version de langage du projet doit être au moins « C# 11 ».
+ The project's language version has to be at least 'C# 12'.
+ La version de langage du projet doit être au moins « C# 11 ».
- Language version is required to be at least C# 11
- La version du langage doit être au moins C# 11
+ Language version is required to be at least C# 12
+ La version du langage doit être au moins C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf
index f418a83d0d422e..27d10a7ee5f9f2 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- La versione del linguaggio del progetto deve essere almeno 'C# 11'.
+ The project's language version has to be at least 'C# 12'.
+ La versione del linguaggio del progetto deve essere almeno 'C# 11'.
- Language version is required to be at least C# 11
- La versione del linguaggio deve essere almeno C# 11
+ Language version is required to be at least C# 12
+ La versione del linguaggio deve essere almeno C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf
index ba59cfba40a89b..24621bcc8b3d22 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- プロジェクトの言語バージョンは少なくとも 'C# 11' である必要があります。
+ The project's language version has to be at least 'C# 12'.
+ プロジェクトの言語バージョンは少なくとも 'C# 11' である必要があります。
- Language version is required to be at least C# 11
- 言語バージョンは少なくとも C# 11 である必要があります
+ Language version is required to be at least C# 12
+ 言語バージョンは少なくとも C# 11 である必要があります
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf
index 10b9b107c4aade..217a0cd9f8e54c 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- 프로젝트의 언어 버전은 'C# 11' 이상이어야 합니다.
+ The project's language version has to be at least 'C# 12'.
+ 프로젝트의 언어 버전은 'C# 11' 이상이어야 합니다.
- Language version is required to be at least C# 11
- 언어 버전은 C# 11 이상이어야 합니다.
+ Language version is required to be at least C# 12
+ 언어 버전은 C# 11 이상이어야 합니다.
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf
index 2b558c588ebfb9..0b24813a77a805 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- Wersja językowa projektu musi mieć wartość co najmniej „C# 11”.
+ The project's language version has to be at least 'C# 12'.
+ Wersja językowa projektu musi mieć wartość co najmniej „C# 11”.
- Language version is required to be at least C# 11
- Wymagana jest wersja językowa co najmniej C# 11
+ Language version is required to be at least C# 12
+ Wymagana jest wersja językowa co najmniej C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf
index 9d2a51c6aa9c96..0ad700e64e9ebd 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- A versão do idioma do projeto deve ser no mínimo 'C# 11'.
+ The project's language version has to be at least 'C# 12'.
+ A versão do idioma do projeto deve ser no mínimo 'C# 11'.
- Language version is required to be at least C# 11
- A versão do idioma deve ser pelo menos C# 11
+ Language version is required to be at least C# 12
+ A versão do idioma deve ser pelo menos C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf
index 1ed03c55891a9e..5e53330060c30b 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- Версия языка проекта должна быть не ниже "C# 11".
+ The project's language version has to be at least 'C# 12'.
+ Версия языка проекта должна быть не ниже "C# 11".
- Language version is required to be at least C# 11
- Версия языка должна быть не ниже C# 11
+ Language version is required to be at least C# 12
+ Версия языка должна быть не ниже C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf
index 8a6dbf76bab7f7..cfaea488fd195d 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- Projenin dil sürümü en az 'C# 11' olmalıdır.
+ The project's language version has to be at least 'C# 12'.
+ Projenin dil sürümü en az 'C# 11' olmalıdır.
- Language version is required to be at least C# 11
- Dil sürümünün en az C# 11 olması gerekir
+ Language version is required to be at least C# 12
+ Dil sürümünün en az C# 11 olması gerekir
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf
index 9d0c0eb3a5d6dd..3dfb711b39b4eb 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- 项目的语言版本必须至少为 "C# 11"。
+ The project's language version has to be at least 'C# 12'.
+ 项目的语言版本必须至少为 "C# 11"。
- Language version is required to be at least C# 11
- 语言版本必须至少为 C# 11
+ Language version is required to be at least C# 12
+ 语言版本必须至少为 C# 11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf
index dc6ded618c8e94..9917b18949880e 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf
@@ -28,13 +28,13 @@
- The project's language version has to be at least 'C# 11'.
- 專案的語言版本必須至少為 'C# 11'。
+ The project's language version has to be at least 'C# 12'.
+ 專案的語言版本必須至少為 'C# 11'。
- Language version is required to be at least C# 11
- 語言版本要求至少為 C#11
+ Language version is required to be at least C# 12
+ 語言版本要求至少為 C#11
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs
index 56dddc6f8bc83b..eea01092667e8d 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs
@@ -8,7 +8,6 @@
using System.Globalization;
using System.Linq;
using System.Reflection;
-using System.Text;
#if BUILDING_SOURCE_GENERATOR_TESTS
using Microsoft.Extensions.Configuration;
#endif
@@ -2037,6 +2036,7 @@ public void ComplexObj_As_Enumerable_Element()
ValidateGeolocation(obj);
}
+#if !BUILDING_SOURCE_GENERATOR_TESTS
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
public void TraceSwitchTest()
{
@@ -2056,6 +2056,7 @@ public void TraceSwitchTest()
Assert.Equal("Info", ts.Value);
#endif // NETCOREAPP
}
+#endif
private void ValidateGeolocation(IGeolocation location)
{
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Collections.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Collections.generated.txt
index 2149dcaaa07141..528847cfeb3a37 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Collections.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Collections.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static T? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -18,11 +25,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 17)]
+ public static T? Get(this IConfiguration configuration) => (T?)(GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClassWithCustomCollections = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "CustomDictionary", "CustomList", "IReadOnlyList", "IReadOnlyDictionary" });
public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions)
@@ -46,16 +60,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref Program.CustomDictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -67,11 +76,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.CustomList obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -83,11 +87,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -99,11 +98,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref ICollection obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -115,11 +109,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref IReadOnlyList obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
if (obj is not ICollection temp)
{
return;
@@ -136,11 +125,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -152,11 +136,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref IDictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -168,11 +147,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref IReadOnlyDictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
if (obj is not IDictionary temp)
{
return;
@@ -189,11 +163,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClassWithCustomCollections obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClassWithCustomCollections), s_configKeys_ProgramMyClassWithCustomCollections, configuration, binderOptions);
if (AsConfigWithChildren(configuration.GetSection("CustomDictionary")) is IConfigurationSection section1)
@@ -229,6 +198,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -281,7 +251,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -298,5 +268,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind.generated.txt
index 406e8db6716777..36ac12fd31f83d 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind.generated.txt
@@ -2,18 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);
-
- /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj, global::System.Action? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetBinderOptions(configureOptions));
+ using System;
+ using System.CodeDom.Compiler;
- /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration.GetSection(key), ref obj, binderOptions: null);
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -23,20 +24,72 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+ #region IConfiguration extensions.
+ /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
+ [InterceptsLocationAttribute(@"src-0.cs", 13, 18)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
- public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, binderOptions: null);
+ }
+
+ /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 24)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj, Action? configureOptions)
+ {
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, GetBinderOptions(configureOptions));
+ }
+
+ /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 24)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, string key, object? obj)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration.GetSection(key), ref typedObj, binderOptions: null);
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -48,11 +101,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -64,11 +112,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
@@ -81,11 +124,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -120,6 +158,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -163,7 +202,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -180,5 +219,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance.generated.txt
index 106e01795369e2..02fb06957bb3d5 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -17,20 +24,36 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
-
- public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ #region IConfiguration extensions.
+ /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, binderOptions: null);
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -42,11 +65,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -58,11 +76,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
@@ -75,11 +88,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -114,6 +122,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -156,5 +165,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt
index a1cb7d6b93b5d0..4703980996b889 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Instance_BinderOptions.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj, global::System.Action? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetBinderOptions(configureOptions));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -17,20 +24,36 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
-
- public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ #region IConfiguration extensions.
+ /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, object? obj, Action? configureOptions)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration, ref typedObj, GetBinderOptions(configureOptions));
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -42,11 +65,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -58,11 +76,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
@@ -75,11 +88,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -114,6 +122,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -157,7 +166,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -174,5 +183,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Key_Instance.generated.txt
index f3ee8a9ff43840..99371296997168 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Key_Instance.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Bind_Key_Instance.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
- public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration.GetSection(key), ref obj, binderOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -17,20 +24,36 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
- private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
-
- public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ #region IConfiguration extensions.
+ /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static void Bind_ProgramMyClass(this IConfiguration configuration, string key, object? obj)
{
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
+ var typedObj = (Program.MyClass)obj;
+ BindCore(configuration.GetSection(key), ref typedObj, binderOptions: null);
+ }
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
+ private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" });
+
+ public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
+ {
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -42,11 +65,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -58,11 +76,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!(obj.TryGetValue(section.Key, out Program.MyClass2? element) && element is not null))
@@ -75,11 +88,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -114,6 +122,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -156,5 +165,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get.generated.txt
index fb71c70b4dd3bd..3e6ce1459b289a 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get.generated.txt
@@ -2,21 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static T? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
-
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static T? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action? configureOptions) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions) ?? default(T));
-
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, global::System.Action? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions);
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -26,11 +24,30 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 38)]
+ public static T? Get(this IConfiguration configuration) => (T?)(GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 36)]
+ public static T? Get(this IConfiguration configuration, Action? configureOptions) => (T?)(GetCore(configuration, typeof(T), configureOptions) ?? default(T));
+
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 13, 36)]
+ public static object? Get(this IConfiguration configuration, Type type) => GetCore(configuration, type, configureOptions: null);
+
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 36)]
+ public static object? Get(this IConfiguration configuration, Type type, Action? configureOptions) => GetCore(configuration, type, configureOptions);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" });
@@ -54,24 +71,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
BindCore(configuration, ref obj, binderOptions);
return obj;
}
-
- if (type == typeof(Program.MyClass2))
+ else if (type == typeof(Program.MyClass2))
{
var obj = new Program.MyClass2();
BindCore(configuration, ref obj, binderOptions);
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -83,11 +94,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
var temp2 = new List();
BindCore(configuration, ref temp2, binderOptions);
int originalCount = obj.Length;
@@ -97,11 +103,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -113,11 +114,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -154,11 +150,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value15)
@@ -167,6 +158,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -219,7 +211,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -236,5 +228,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue.generated.txt
index c9d49faa937244..e4bcaf6a9b7c95 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue.generated.txt
@@ -2,21 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Extracts the value with the specified key and converts it to the specified type.
- public static T? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? default(T));
-
- /// Extracts the value with the specified key and converts it to the specified type.
- public static T? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
-
- /// Extracts the value with the specified key and converts it to the specified type.
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key);
+ using System;
+ using System.CodeDom.Compiler;
- /// Extracts the value with the specified key and converts it to the specified type.
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key, object? defaultValue) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key) ?? defaultValue;
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -25,11 +23,30 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 13, 18)]
+ public static T? GetValue(this IConfiguration configuration, string key) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? default(T));
+
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 16, 24)]
+ public static T? GetValue(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
+
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 14, 24)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key) => BindingExtensions.GetValueCore(configuration, type, key);
+
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 17, 24)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
@@ -48,18 +65,15 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
return ParseInt(value, () => section.Path);
}
-
- if (type == typeof(bool?))
+ else if (type == typeof(bool?))
{
return ParseBool(value, () => section.Path);
}
-
- if (type == typeof(byte[]))
+ else if (type == typeof(byte[]))
{
return ParseByteArray(value, () => section.Path);
}
-
- if (type == typeof(CultureInfo))
+ else if (type == typeof(CultureInfo))
{
return ParseCultureInfo(value, () => section.Path);
}
@@ -114,5 +128,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(CultureInfo)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key.generated.txt
index 17c963bd980a70..2438cf530ca4ce 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Extracts the value with the specified key and converts it to the specified type.
- public static T? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -16,11 +23,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 10, 20)]
+ public static T? GetValue(this IConfiguration configuration, string key) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
@@ -54,5 +68,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt
index 1148109b9f5a81..e6db24d522f3c9 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_T_Key_DefaultValue.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Extracts the value with the specified key and converts it to the specified type.
- public static T? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -16,11 +23,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 20)]
+ public static T? GetValue(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
@@ -54,5 +68,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt
index c833b20f18dcfe..a36f9fafebcff8 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Extracts the value with the specified key and converts it to the specified type.
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -16,11 +23,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 10, 20)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key) => BindingExtensions.GetValueCore(configuration, type, key);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
@@ -54,5 +68,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt
index f773f79ce6c2c0..356f6bb1a933e2 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/GetValue_TypeOf_Key_DefaultValue.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Extracts the value with the specified key and converts it to the specified type.
- public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key, object? defaultValue) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetValueCore(configuration, type, key) ?? defaultValue;
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -16,11 +23,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System;
using System.CodeDom.Compiler;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Extracts the value with the specified key and converts it to the specified type.
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 20)]
+ public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
public static object? GetValueCore(this IConfiguration configuration, Type type, string key)
{
if (configuration is null)
@@ -54,5 +68,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(CultureInfo)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T.generated.txt
index de8201fe6fed2c..85d0901de3ff60 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static T? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -17,11 +24,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 40)]
+ public static T? Get(this IConfiguration configuration) => (T?)(GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions)
@@ -45,16 +59,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -66,11 +75,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
var temp1 = new List();
BindCore(configuration, ref temp1, binderOptions);
int originalCount = obj.Length;
@@ -80,11 +84,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -96,11 +95,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -135,6 +129,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -187,7 +182,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -204,5 +199,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T_BinderOptions.generated.txt
index 34fadacace146d..d394cc7b269f74 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T_BinderOptions.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_T_BinderOptions.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static T? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action? configureOptions) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, typeof(T), configureOptions) ?? default(T));
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -17,11 +24,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 40)]
+ public static T? Get(this IConfiguration configuration, Action? configureOptions) => (T?)(GetCore(configuration, typeof(T), configureOptions) ?? default(T));
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" });
public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions)
@@ -45,16 +59,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -66,11 +75,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
var temp1 = new List();
BindCore(configuration, ref temp1, binderOptions);
int originalCount = obj.Length;
@@ -80,11 +84,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -96,11 +95,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -135,6 +129,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -187,7 +182,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -204,5 +199,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf.generated.txt
index 16a98c931a705f..83cd88561310ab 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions: null);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -17,11 +24,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 40)]
+ public static object? Get(this IConfiguration configuration, Type type) => GetCore(configuration, type, configureOptions: null);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" });
public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions)
@@ -45,16 +59,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value1)
@@ -63,6 +72,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -115,7 +125,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -132,5 +142,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt
index 8d1ee9ed3cd9a3..91714c80cd0136 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/ConfigurationBinder/Get_TypeOf_BinderOptions.generated.txt
@@ -2,12 +2,19 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedConfigurationBinder
+namespace System.Runtime.CompilerServices
{
- /// Attempts to bind the configuration instance to a new instance of type T.
- public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, global::System.Action? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.GetCore(configuration, type, configureOptions);
+ using System;
+ using System.CodeDom.Compiler;
+
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
+ {
+ }
+ }
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
@@ -17,11 +24,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region IConfiguration extensions.
+ /// Attempts to bind the configuration instance to a new instance of type T.
+ [InterceptsLocationAttribute(@"src-0.cs", 11, 20)]
+ public static object? Get(this IConfiguration configuration, Type type, Action? configureOptions) => GetCore(configuration, type, configureOptions);
+ #endregion IConfiguration extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" });
public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions)
@@ -45,16 +59,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
return obj;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions);
if (configuration["MyInt"] is string value1)
@@ -63,6 +72,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -115,7 +125,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -132,5 +142,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/BindConfiguration.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/BindConfiguration.generated.txt
index a74dbfdd04b5b9..88b35037c22c3f 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/BindConfiguration.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/BindConfiguration.generated.txt
@@ -2,31 +2,18 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedOptionsBuilderBinder
+namespace System.Runtime.CompilerServices
{
- /// Registers the dependency injection container to bind against the obtained from the DI service provider.
- public static global::Microsoft.Extensions.Options.OptionsBuilder BindConfiguration(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, global::System.Action? configureOptions = null) where TOptions : class
- {
- if (optionsBuilder is null)
- {
- throw new global::System.ArgumentNullException(nameof(optionsBuilder));
- }
+ using System;
+ using System.CodeDom.Compiler;
- if (configSectionPath is null)
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
+ {
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configSectionPath));
}
-
- optionsBuilder.Configure((obj, configuration) =>
- {
- global::Microsoft.Extensions.Configuration.IConfiguration section = string.Equals(string.Empty, configSectionPath, global::System.StringComparison.OrdinalIgnoreCase) ? configuration : configuration.GetSection(configSectionPath);
- global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(section, obj, typeof(TOptions), configureOptions);
- });
-
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton, global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource>(optionsBuilder.Services);
- return optionsBuilder;
}
}
@@ -34,31 +21,74 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Options;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region OptionsBuilder extensions.
+ /// Registers the dependency injection container to bind against the obtained from the DI service provider.
+ [InterceptsLocationAttribute(@"src-0.cs", 12, 24)]
+ public static OptionsBuilder BindConfiguration(this OptionsBuilder optionsBuilder, string configSectionPath, Action? configureOptions = null) where TOptions : class
+ {
+ if (optionsBuilder is null)
+ {
+ throw new ArgumentNullException(nameof(optionsBuilder));
+ }
+
+ if (configSectionPath is null)
+ {
+ throw new ArgumentNullException(nameof(configSectionPath));
+ }
+
+ optionsBuilder.Configure((obj, configuration) =>
+ {
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ IConfiguration section = string.Equals(string.Empty, configSectionPath, StringComparison.OrdinalIgnoreCase) ? configuration : configuration.GetSection(configSectionPath);
+ BindCoreMain(section, obj, typeof(TOptions), configureOptions);
+ });
+
+ optionsBuilder.Services.AddSingleton, ConfigurationChangeTokenSource>();
+ return optionsBuilder;
+ }
+ #endregion OptionsBuilder extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
@@ -66,16 +96,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -87,11 +112,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -110,6 +130,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -162,7 +183,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -179,5 +200,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T.generated.txt
index ac53b58f24da23..633196e7a742d5 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T.generated.txt
@@ -2,49 +2,18 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedOptionsBuilderBinder
+namespace System.Runtime.CompilerServices
{
- /// Registers a configuration instance which will bind against.
- public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, global::Microsoft.Extensions.Configuration.IConfiguration configuration) where TOptions : class
- {
- return global::GeneratedOptionsBuilderBinder.Bind(optionsBuilder, configuration, configureOptions: null);
- }
-
- /// Registers a configuration instance which will bind against.
- public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action? configureOptions) where TOptions : class
- {
- if (optionsBuilder is null)
- {
- throw new global::System.ArgumentNullException(nameof(optionsBuilder));
- }
-
- global::GeneratedServiceCollectionBinder.Configure(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
- return optionsBuilder;
- }
-}
+ using System;
+ using System.CodeDom.Compiler;
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
-{
- /// Registers a configuration instance which TOptions will bind against.
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action? configureOptions) where TOptions : class
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
{
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
-
- if (configuration is null)
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
@@ -52,31 +21,79 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Options;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region OptionsBuilder extensions.
+ /// Registers a configuration instance which will bind against.
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 24)]
+ public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration configuration) where TOptions : class
+ {
+ return Bind(optionsBuilder, configuration, configureOptions: null);
+ }
+
+ /// Registers a configuration instance which will bind against.
+ public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration configuration, Action? configureOptions) where TOptions : class
+ {
+ if (optionsBuilder is null)
+ {
+ throw new ArgumentNullException(nameof(optionsBuilder));
+ }
+
+ Configure(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
+ return optionsBuilder;
+ }
+ #endregion OptionsBuilder extensions.
+
+ #region IServiceCollection extensions.
+ /// Registers a configuration instance which TOptions will bind against.
+ public static IServiceCollection Configure(this IServiceCollection services, string? name, IConfiguration configuration, Action? configureOptions) where TOptions : class
+ {
+ if (services is null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ if (configuration is null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ OptionsServiceCollectionExtensions.AddOptions(services);
+ services.AddSingleton>(new ConfigurationChangeTokenSource(name, configuration));
+ return services.AddSingleton>(new Microsoft.Extensions.Options.ConfigureNamedOptions(name, obj => BindCoreMain(configuration, obj, typeof(TOptions)configureOptions)));
+ }
+ #endregion IServiceCollection extensions.
+
+ #region Core binding extensions.
private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" });
- public static void BindCoreUntyped(this IConfiguration configuration, object obj, Type type, Action? configureOptions)
+ public static void BindCoreMain(IConfiguration configuration, object obj, Type type, Action? configureOptions)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
- BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+ if (obj is null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
if (!HasValueOrChildren(configuration))
{
return;
}
+ BinderOptions? binderOptions = GetBinderOptions(configureOptions);
+
if (type == typeof(Program.MyClass))
{
var temp = (Program.MyClass)obj;
@@ -84,16 +101,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
return;
}
- throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
+ throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (section.Value is string value)
@@ -105,11 +117,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions)
{
- if (obj is null)
- {
- throw new ArgumentNullException(nameof(obj));
- }
-
ValidateConfigurationKeys(typeof(Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions);
obj.MyString = configuration["MyString"]!;
@@ -128,6 +135,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
}
}
+
/// If required by the binder options, validates that there are no unknown keys in the input configuration object.
public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
@@ -180,7 +188,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
if (binderOptions.BindNonPublicProperties)
{
- throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
+ throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
}
return binderOptions;
@@ -197,5 +205,6 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
+ #endregion Core binding extensions.
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T_BinderOptions.generated.txt
index fd3ec70a8a328b..fb5b4b4ad721d8 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T_BinderOptions.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/OptionsBuilder/Bind_T_BinderOptions.generated.txt
@@ -2,43 +2,18 @@
#nullable enable
#pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedOptionsBuilderBinder
+namespace System.Runtime.CompilerServices
{
- /// Registers a configuration instance which will bind against.
- public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action? configureOptions) where TOptions : class
- {
- if (optionsBuilder is null)
- {
- throw new global::System.ArgumentNullException(nameof(optionsBuilder));
- }
-
- global::GeneratedServiceCollectionBinder.Configure(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
- return optionsBuilder;
- }
-}
+ using System;
+ using System.CodeDom.Compiler;
-/// Generated helper providing an AOT and linking compatible implementation for configuration binding.
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
-internal static class GeneratedServiceCollectionBinder
-{
- /// Registers a configuration instance which TOptions will bind against.
- public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, string? name, global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action? configureOptions) where TOptions : class
+ [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ file sealed class InterceptsLocationAttribute : Attribute
{
- if (services is null)
- {
- throw new global::System.ArgumentNullException(nameof(services));
- }
-
- if (configuration is null)
+ public InterceptsLocationAttribute(string filePath, int line, int column)
{
- throw new global::System.ArgumentNullException(nameof(configuration));
}
-
- global::Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.AddOptions(services);
- global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, new global::Microsoft.Extensions.Options.ConfigurationChangeTokenSource(name, configuration));
- return global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton>(services, new global::Microsoft.Extensions.Options.ConfigureNamedOptions(name, obj => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCoreUntyped(configuration, obj, typeof(TOptions), configureOptions)));
}
}
@@ -46,31 +21,73 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.Options;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
+ using System.Runtime.CompilerServices;
- /// Provide core binding logic.
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
- file static class CoreBindingHelper
+ file static class BindingExtensions
{
+ #region OptionsBuilder extensions.
+ /// Registers a configuration instance which will bind against.
+ [InterceptsLocationAttribute(@"src-0.cs", 15, 24)]
+ public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration configuration, Action? configureOptions) where TOptions : class
+ {
+ if (optionsBuilder is null)
+ {
+ throw new ArgumentNullException(nameof(optionsBuilder));
+ }
+
+ Configure(optionsBuilder.Services, optionsBuilder.Name, configuration, configureOptions);
+ return optionsBuilder;
+ }
+ #endregion OptionsBuilder extensions.
+
+ #region IServiceCollection extensions.
+ ///