From a999c40a1ef8a61c2a1cecf1cf873345963eaa48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Rozto=C4=8Dil?= Date: Fri, 19 Sep 2025 22:29:06 +0200 Subject: [PATCH 1/3] Merge pull request #63734 from dotnet/oroztocil/validation-sg-fix-backport [release/10.0] [backport fix] Fix Validation source generator deployment for non-Web SDKs --- src/Shared/RoslynUtils/WellKnownTypes.cs | 39 ++++++++++++++++--- .../gen/Extensions/ITypeSymbolExtensions.cs | 12 +++--- .../ValidationsGenerator.TypesParser.cs | 8 ++-- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/Shared/RoslynUtils/WellKnownTypes.cs b/src/Shared/RoslynUtils/WellKnownTypes.cs index deb2def60b60..05925ddf68bc 100644 --- a/src/Shared/RoslynUtils/WellKnownTypes.cs +++ b/src/Shared/RoslynUtils/WellKnownTypes.cs @@ -19,7 +19,6 @@ public static WellKnownTypes GetOrCreate(Compilation compilation) => private readonly INamedTypeSymbol?[] _lazyWellKnownTypes; private readonly Compilation _compilation; - private readonly INamedTypeSymbol _missingTypeSymbol; static WellKnownTypes() { @@ -52,7 +51,6 @@ private WellKnownTypes(Compilation compilation) { _lazyWellKnownTypes = new INamedTypeSymbol?[WellKnownTypeData.WellKnownTypeNames.Length]; _compilation = compilation; - _missingTypeSymbol = compilation.GetTypeByMetadataName(typeof(MissingType).FullName!)!; } public INamedTypeSymbol Get(SpecialType type) @@ -60,7 +58,28 @@ public INamedTypeSymbol Get(SpecialType type) return _compilation.GetSpecialType(type); } + /// + /// Returns the type symbol for the specified well-known type, or throws if the type cannot be found. + /// public INamedTypeSymbol Get(WellKnownTypeData.WellKnownType type) + { + return Get(type, throwOnNotFound: true); + } + + /// + /// Returns the type symbol for the specified well-known type, or a special marker type symbol if the type cannot be found. + /// + /// + /// We use a special marker type for cases where some types can be legitimately missing. + /// E.g. The Microsoft.Extensions.Validation source generator checks against some types + /// from the shared framework which are missing in Blazor WebAssembly SDK projects. + /// + public INamedTypeSymbol GetOptional(WellKnownTypeData.WellKnownType type) + { + return Get(type, throwOnNotFound: false); + } + + private INamedTypeSymbol Get(WellKnownTypeData.WellKnownType type, bool throwOnNotFound) { var index = (int)type; var symbol = _lazyWellKnownTypes[index]; @@ -71,12 +90,22 @@ public INamedTypeSymbol Get(WellKnownTypeData.WellKnownType type) // Symbol hasn't been added to the cache yet. // Resolve symbol from name, cache, and return. - return GetAndCache(index); + return GetAndCache(index, throwOnNotFound); } - private INamedTypeSymbol GetAndCache(int index) + private INamedTypeSymbol GetAndCache(int index, bool throwOnNotFound) { - var result = GetTypeByMetadataNameInTargetAssembly(WellKnownTypeData.WellKnownTypeNames[index]) ?? _missingTypeSymbol; + var result = GetTypeByMetadataNameInTargetAssembly(WellKnownTypeData.WellKnownTypeNames[index]); + + if (result == null && throwOnNotFound) + { + throw new InvalidOperationException($"Failed to resolve well-known type '{WellKnownTypeData.WellKnownTypeNames[index]}'."); + } + else + { + result ??= _compilation.GetTypeByMetadataName(typeof(MissingType).FullName!)!; + } + Interlocked.CompareExchange(ref _lazyWellKnownTypes[index], result, null); // GetTypeByMetadataName should always return the same instance for a name. diff --git a/src/Validation/gen/Extensions/ITypeSymbolExtensions.cs b/src/Validation/gen/Extensions/ITypeSymbolExtensions.cs index 4b34054571aa..63261c68a85d 100644 --- a/src/Validation/gen/Extensions/ITypeSymbolExtensions.cs +++ b/src/Validation/gen/Extensions/ITypeSymbolExtensions.cs @@ -95,13 +95,13 @@ internal static bool ImplementsInterface(this ITypeSymbol type, ITypeSymbol inte // types themselves so we short-circuit on them. internal static bool IsExemptType(this ITypeSymbol type, WellKnownTypes wellKnownTypes) { - return SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_HttpContext)) - || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_HttpRequest)) - || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_HttpResponse)) + return SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.GetOptional(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_HttpContext)) + || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.GetOptional(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_HttpRequest)) + || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.GetOptional(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_HttpResponse)) || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.System_Threading_CancellationToken)) - || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_IFormCollection)) - || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_IFormFileCollection)) - || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_IFormFile)) + || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.GetOptional(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_IFormCollection)) + || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.GetOptional(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_IFormFileCollection)) + || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.GetOptional(WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_IFormFile)) || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.System_IO_Stream)) || SymbolEqualityComparer.Default.Equals(type, wellKnownTypes.Get(WellKnownTypeData.WellKnownType.System_IO_Pipelines_PipeReader)); } diff --git a/src/Validation/gen/Parsers/ValidationsGenerator.TypesParser.cs b/src/Validation/gen/Parsers/ValidationsGenerator.TypesParser.cs index cc0624fdfb93..71466a8a547b 100644 --- a/src/Validation/gen/Parsers/ValidationsGenerator.TypesParser.cs +++ b/src/Validation/gen/Parsers/ValidationsGenerator.TypesParser.cs @@ -27,9 +27,9 @@ internal ImmutableArray ExtractValidatableTypes(IInvocationOper ? method.Parameters : []; - var fromServiceMetadataSymbol = wellKnownTypes.Get( + var fromServiceMetadataSymbol = wellKnownTypes.GetOptional( WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_Metadata_IFromServiceMetadata); - var fromKeyedServiceAttributeSymbol = wellKnownTypes.Get( + var fromKeyedServiceAttributeSymbol = wellKnownTypes.GetOptional( WellKnownTypeData.WellKnownType.Microsoft_Extensions_DependencyInjection_FromKeyedServicesAttribute); var skipValidationAttributeSymbol = wellKnownTypes.Get( WellKnownTypeData.WellKnownType.Microsoft_Extensions_Validation_SkipValidationAttribute); @@ -127,9 +127,9 @@ internal ImmutableArray ExtractValidatableMembers(ITypeSymb var members = new List(); var resolvedRecordProperty = new List(); - var fromServiceMetadataSymbol = wellKnownTypes.Get( + var fromServiceMetadataSymbol = wellKnownTypes.GetOptional( WellKnownTypeData.WellKnownType.Microsoft_AspNetCore_Http_Metadata_IFromServiceMetadata); - var fromKeyedServiceAttributeSymbol = wellKnownTypes.Get( + var fromKeyedServiceAttributeSymbol = wellKnownTypes.GetOptional( WellKnownTypeData.WellKnownType.Microsoft_Extensions_DependencyInjection_FromKeyedServicesAttribute); var jsonIgnoreAttributeSymbol = wellKnownTypes.Get( WellKnownTypeData.WellKnownType.System_Text_Json_Serialization_JsonIgnoreAttribute); From 07545ad7f10472c54d54eb2aa4b0dbee44f3e795 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Sep 2025 16:08:55 -0700 Subject: [PATCH 2/3] Move setupstrings.wxl to LCID folder (#63749) Co-authored-by: wtgodbe --- .../ANCMIISExpressV2/AncmIISExpressV2.wixproj | 2 +- .../Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj | 2 +- .../AspNetCoreModule-Setup/{ => LCID/1033}/setupstrings.wxl | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/Installers/Windows/AspNetCoreModule-Setup/{ => LCID/1033}/setupstrings.wxl (100%) diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/AncmIISExpressV2.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/AncmIISExpressV2.wixproj index 65f5dac503d6..1ea503e35bce 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/AncmIISExpressV2.wixproj +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/AncmIISExpressV2.wixproj @@ -30,7 +30,7 @@ iisca.wxs - + setupstrings.wxl diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj index 15805dc5d15b..b906475388a8 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj +++ b/src/Installers/Windows/AspNetCoreModule-Setup/ANCMV2/AncmV2.wixproj @@ -25,7 +25,7 @@ iisca.wxs - + setupstrings.wxl diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/LCID/1033/setupstrings.wxl similarity index 100% rename from src/Installers/Windows/AspNetCoreModule-Setup/setupstrings.wxl rename to src/Installers/Windows/AspNetCoreModule-Setup/LCID/1033/setupstrings.wxl From b848011064f55b305b051344c51405997cb640fe Mon Sep 17 00:00:00 2001 From: wtgodbe Date: Mon, 22 Sep 2025 13:34:24 -0700 Subject: [PATCH 3/3] Don't change loc --- .../Windows/AspNetCoreModule-Setup/LCID/1033/setupstrings.wxl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/LCID/1033/setupstrings.wxl b/src/Installers/Windows/AspNetCoreModule-Setup/LCID/1033/setupstrings.wxl index 22640d5eafa6..374b00ef6e92 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/LCID/1033/setupstrings.wxl +++ b/src/Installers/Windows/AspNetCoreModule-Setup/LCID/1033/setupstrings.wxl @@ -48,4 +48,4 @@ - + \ No newline at end of file