From 304dd3ddb136ae2909ca0c1f14eebe6f930720db Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Thu, 18 May 2023 17:24:54 -0700 Subject: [PATCH 01/13] Options validation source generator --- .../Common/src/System/ThrowHelper.cs | 40 + .../gen/DiagDescriptors.cs | 95 + .../gen/DiagDescriptorsBase.cs | 30 + .../gen/Emitter.cs | 365 ++++ .../gen/EmitterBase.cs | 101 + .../gen/Generator.cs | 47 + .../gen/GeneratorUtilities.cs | 131 ++ ...Extensions.Options.SourceGeneration.csproj | 36 + .../gen/Model/ValidatedMember.cs | 20 + .../gen/Model/ValidatedModel.cs | 13 + .../gen/Model/ValidationAttributeInfo.cs | 13 + .../gen/Model/ValidatorType.cs | 16 + .../gen/Parser.cs | 663 +++++++ .../gen/ParserUtilities.cs | 75 + .../gen/Resources.resx | 198 ++ .../gen/Resources/Strings.resx | 198 ++ .../gen/Resources/xlf/Strings.cs.xlf | 137 ++ .../gen/Resources/xlf/Strings.de.xlf | 137 ++ .../gen/Resources/xlf/Strings.es.xlf | 137 ++ .../gen/Resources/xlf/Strings.fr.xlf | 137 ++ .../gen/Resources/xlf/Strings.it.xlf | 137 ++ .../gen/Resources/xlf/Strings.ja.xlf | 137 ++ .../gen/Resources/xlf/Strings.ko.xlf | 137 ++ .../gen/Resources/xlf/Strings.pl.xlf | 137 ++ .../gen/Resources/xlf/Strings.pt-BR.xlf | 137 ++ .../gen/Resources/xlf/Strings.ru.xlf | 137 ++ .../gen/Resources/xlf/Strings.tr.xlf | 137 ++ .../gen/Resources/xlf/Strings.zh-Hans.xlf | 137 ++ .../gen/Resources/xlf/Strings.zh-Hant.xlf | 137 ++ .../gen/SymbolHolder.cs | 20 + .../gen/SymbolLoader.cs | 68 + .../gen/TypeDeclarationSyntaxReceiver.cs | 43 + .../ref/Microsoft.Extensions.Options.cs | 18 + .../src/OptionsValidatorAttribute.cs | 16 + .../src/ValidateEnumeratedItemsAttribute.cs | 45 + .../src/ValidateObjectMembersAttribute.cs | 44 + .../Baselines/NetCoreApp/Validators.g.cs | 1756 +++++++++++++++++ .../Baselines/NetFX/Validators.g.cs | 1748 ++++++++++++++++ .../SourceGenerationTests/EmitterTests.cs | 61 + .../Extensions/EmptyReadOnlyList.cs | 58 + .../Extensions/EmptyReadonlyDictionary.cs | 63 + .../Extensions/TimeSpanAttribute.cs | 160 ++ .../Extensions/ValidationContextExtensions.cs | 29 + .../Generated/CustomAttrTests.cs | 39 + .../Generated/EnumerationTests.cs | 93 + .../Generated/FieldTests.cs | 62 + .../Generated/FunnyStringsTests.cs | 37 + .../Generated/GenericsTests.cs | 49 + .../Generated/MultiModelValidatorTests.cs | 49 + .../Generated/NestedTests.cs | 67 + .../Generated/NoNamespaceTests.cs | 60 + .../Generated/OptionsValidationTests.cs | 442 +++++ .../Generated/RandomMembersTests.cs | 37 + .../Generated/RecordTypesTests.cs | 67 + .../Generated/RepeatedTypesTests.cs | 61 + .../Generated/SelfValidationTests.cs | 37 + .../SourceGenerationTests/Generated/Utils.cs | 31 + .../Generated/ValueTypesTests.cs | 53 + ...ions.Options.SourceGeneration.Tests.csproj | 55 + .../ParserTests.Enumeration.cs | 214 ++ .../SourceGenerationTests/ParserTests.cs | 930 +++++++++ .../Resources/Strings.resx | 201 ++ .../TestClasses/CustomAttr.cs | 68 + .../TestClasses/Enumeration.cs | 93 + .../TestClasses/Fields.cs | 71 + .../TestClasses/FileScopedNamespace.cs | 21 + .../TestClasses/FunnyStrings.cs | 22 + .../TestClasses/Generics.cs | 35 + .../TestClasses/Models.cs | 251 +++ .../TestClasses/MultiModelValidator.cs | 33 + .../TestClasses/Nested.cs | 106 + .../TestClasses/NoNamespace.cs | 45 + .../TestClasses/RandomMembers.cs | 34 + .../TestClasses/RecordTypes.cs | 67 + .../TestClasses/RepeatedTypes.cs | 46 + .../TestClasses/SelfValidation.cs | 33 + .../TestClasses/ValueTypes.cs | 45 + 77 files changed, 11505 insertions(+) create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptorsBase.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Generator.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedMember.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedModel.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Model/ValidationAttributeInfo.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatorType.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Parser.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/ParserUtilities.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources.resx create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.de.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.es.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.fr.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.it.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ja.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ko.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pl.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pt-BR.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ru.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.tr.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hans.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hant.xlf create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/SymbolHolder.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/SymbolLoader.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/gen/TypeDeclarationSyntaxReceiver.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/src/OptionsValidatorAttribute.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/src/ValidateEnumeratedItemsAttribute.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/src/ValidateObjectMembersAttribute.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadOnlyList.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadonlyDictionary.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/TimeSpanAttribute.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/ValidationContextExtensions.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/CustomAttrTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/EnumerationTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FieldTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FunnyStringsTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/GenericsTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/MultiModelValidatorTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NestedTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NoNamespaceTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RandomMembersTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RecordTypesTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RepeatedTypesTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/SelfValidationTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/ValueTypesTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/CustomAttr.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Enumeration.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Fields.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FileScopedNamespace.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FunnyStrings.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Generics.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/MultiModelValidator.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Nested.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/NoNamespace.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RandomMembers.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RecordTypes.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RepeatedTypes.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/SelfValidation.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/ValueTypes.cs diff --git a/src/libraries/Common/src/System/ThrowHelper.cs b/src/libraries/Common/src/System/ThrowHelper.cs index 921394be4cd17..4257c05891e32 100644 --- a/src/libraries/Common/src/System/ThrowHelper.cs +++ b/src/libraries/Common/src/System/ThrowHelper.cs @@ -31,6 +31,46 @@ internal static void ThrowIfNull( [DoesNotReturn] #endif private static void Throw(string? paramName) => throw new ArgumentNullException(paramName); + + /// + /// Throws either an or an + /// if the specified string is or whitespace respectively. + /// + /// String to be checked for or whitespace. + /// The name of the parameter being checked. + /// The original value of . + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NETCOREAPP3_0_OR_GREATER + [return: NotNull] +#endif + public static string IfNullOrWhitespace( +#if NETCOREAPP3_0_OR_GREATER + [NotNull] +#endif + string? argument, + [CallerArgumentExpression(nameof(argument))] string paramName = "") + { +#if !NETCOREAPP3_1_OR_GREATER + if (argument == null) + { + throw new ArgumentNullException(paramName); + } +#endif + + if (string.IsNullOrWhiteSpace(argument)) + { + if (argument == null) + { + throw new ArgumentNullException(paramName); + } + else + { + throw new ArgumentException(paramName, "Argument is whitespace"); + } + } + + return argument; + } } } diff --git a/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs b/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs new file mode 100644 index 0000000000000..e76363fee0e94 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using System; + +namespace Microsoft.Extensions.Options.Generators +{ + internal sealed class DiagDescriptors : DiagDescriptorsBase + { + private const string Category = "Microsoft.Extensions.Options.SourceGeneration"; + + public static DiagnosticDescriptor CantUseWithGenericTypes { get; } = Make( + id: "SYSLIB1201", + title: SR.CantUseWithGenericTypesTitle, + messageFormat: SR.CantUseWithGenericTypesMessage, + category: Category); + + public static DiagnosticDescriptor NoEligibleMember { get; } = Make( + id: "SYSLIB1202", + title: SR.NoEligibleMemberTitle, + messageFormat: SR.NoEligibleMemberMessage, + category: Category, + defaultSeverity: DiagnosticSeverity.Warning); + + public static DiagnosticDescriptor NoEligibleMembersFromValidator { get; } = Make( + id: "SYSLIB1203", + title: SR.NoEligibleMembersFromValidatorTitle, + messageFormat: SR.NoEligibleMembersFromValidatorMessage, + category: Category, + defaultSeverity: DiagnosticSeverity.Warning); + + public static DiagnosticDescriptor DoesntImplementIValidateOptions { get; } = Make( + id: "SYSLIB1204", + title: SR.DoesntImplementIValidateOptionsTitle, + messageFormat: SR.DoesntImplementIValidateOptionsMessage, + category: Category); + + public static DiagnosticDescriptor AlreadyImplementsValidateMethod { get; } = Make( + id: "SYSLIB1205", + title: SR.AlreadyImplementsValidateMethodTitle, + messageFormat: SR.AlreadyImplementsValidateMethodMessage, + category: Category); + + public static DiagnosticDescriptor MemberIsInaccessible { get; } = Make( + id: "SYSLIB1206", + title: SR.MemberIsInaccessibleTitle, + messageFormat: SR.MemberIsInaccessibleMessage, + category: Category); + + public static DiagnosticDescriptor NotEnumerableType { get; } = Make( + id: "SYSLIB1207", + title: SR.NotEnumerableTypeTitle, + messageFormat: SR.NotEnumerableTypeMessage, + category: Category); + + public static DiagnosticDescriptor ValidatorsNeedSimpleConstructor { get; } = Make( + id: "SYSLIB1208", + title: SR.ValidatorsNeedSimpleConstructorTitle, + messageFormat: SR.ValidatorsNeedSimpleConstructorMessage, + category: Category); + + public static DiagnosticDescriptor CantBeStaticClass { get; } = Make( + id: "SYSLIB1209", + title: SR.CantBeStaticClassTitle, + messageFormat: SR.CantBeStaticClassMessage, + category: Category); + + public static DiagnosticDescriptor NullValidatorType { get; } = Make( + id: "SYSLIB1210", + title: SR.NullValidatorTypeTitle, + messageFormat: SR.NullValidatorTypeMessage, + category: Category); + + public static DiagnosticDescriptor CircularTypeReferences { get; } = Make( + id: "SYSLIB1211", + title: SR.CircularTypeReferencesTitle, + messageFormat: SR.CircularTypeReferencesMessage, + category: Category); + + public static DiagnosticDescriptor PotentiallyMissingTransitiveValidation { get; } = Make( + id: "SYSLIB1212", + title: SR.PotentiallyMissingTransitiveValidationTitle, + messageFormat: SR.PotentiallyMissingTransitiveValidationMessage, + category: Category, + defaultSeverity: DiagnosticSeverity.Warning); + + public static DiagnosticDescriptor PotentiallyMissingEnumerableValidation { get; } = Make( + id: "SYSLIB1213", + title: SR.PotentiallyMissingEnumerableValidationTitle, + messageFormat: SR.PotentiallyMissingEnumerableValidationMessage, + category: Category, + defaultSeverity: DiagnosticSeverity.Warning); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptorsBase.cs b/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptorsBase.cs new file mode 100644 index 0000000000000..f749e02394a67 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptorsBase.cs @@ -0,0 +1,30 @@ +// 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 Microsoft.CodeAnalysis; + +namespace Microsoft.Extensions.Options.Generators +{ + #pragma warning disable CA1052 // Static holder types should be Static or NotInheritable + internal class DiagDescriptorsBase + #pragma warning restore CA1052 + { + protected static DiagnosticDescriptor Make( + string id, + string title, + string messageFormat, + string category, + DiagnosticSeverity defaultSeverity = DiagnosticSeverity.Error, + bool isEnabledByDefault = true) + { + return new( + id, + title, + messageFormat, + category, + defaultSeverity, + isEnabledByDefault); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs new file mode 100644 index 0000000000000..ebf72a11b3f44 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs @@ -0,0 +1,365 @@ +// 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.Linq; +using System.Threading; + +namespace Microsoft.Extensions.Options.Generators +{ + /// + /// Emits option validation. + /// + internal sealed class Emitter : EmitterBase + { + private const string StaticValidationAttributeHolderClassName = "__Attributes"; + private const string StaticValidatorHolderClassName = "__Validators"; + private const string StaticFieldHolderClassesNamespace = "__OptionValidationStaticInstances"; + private const string StaticValidationAttributeHolderClassFQN = $"global::{StaticFieldHolderClassesNamespace}.{StaticValidationAttributeHolderClassName}"; + private const string StaticValidatorHolderClassFQN = $"global::{StaticFieldHolderClassesNamespace}.{StaticValidatorHolderClassName}"; + private sealed record StaticFieldInfo(string FieldTypeFQN, int FieldOrder, string FieldName, IList InstantiationLines); + + public string Emit( + IEnumerable validatorTypes, + CancellationToken cancellationToken) + { + var staticValidationAttributesDict = new Dictionary(); + var staticValidatorsDict = new Dictionary(); + + foreach (var vt in validatorTypes.OrderBy(static lt => lt.Namespace + "." + lt.Name)) + { + cancellationToken.ThrowIfCancellationRequested(); + GenValidatorType(vt, ref staticValidationAttributesDict, ref staticValidatorsDict); + } + + GenStaticClassWithStaticReadonlyFields(staticValidationAttributesDict.Values, StaticFieldHolderClassesNamespace, StaticValidationAttributeHolderClassName); + GenStaticClassWithStaticReadonlyFields(staticValidatorsDict.Values, StaticFieldHolderClassesNamespace, StaticValidatorHolderClassName); + + return Capture(); + } + + private void GenValidatorType(ValidatorType vt, ref Dictionary staticValidationAttributesDict, ref Dictionary staticValidatorsDict) + { + OutLn("#pragma warning disable CS0618 // Type or member is obsolete"); + + if (vt.Namespace.Length > 0) + { + OutLn($"namespace {vt.Namespace}"); + OutOpenBrace(); + } + + foreach (var p in vt.ParentTypes) + { + OutLn(p); + OutOpenBrace(); + } + + if (vt.IsSynthetic) + { + OutGeneratedCodeAttribute(); + OutLn($"internal sealed partial {vt.DeclarationKeyword} {vt.Name}"); + } + else + { + OutLn($"partial {vt.DeclarationKeyword} {vt.Name}"); + } + + OutOpenBrace(); + + for (var i = 0; i < vt.ModelsToValidate.Count; i++) + { + var modelToValidate = vt.ModelsToValidate[i]; + + GenModelValidationMethod(modelToValidate, vt.IsSynthetic, ref staticValidationAttributesDict, ref staticValidatorsDict); + } + + OutCloseBrace(); + + foreach (var _ in vt.ParentTypes) + { + OutCloseBrace(); + } + + if (vt.Namespace.Length > 0) + { + OutCloseBrace(); + } + } + + private void GenStaticClassWithStaticReadonlyFields(IEnumerable staticFields, string classNamespace, string className) + { + OutLn($"namespace {classNamespace}"); + OutOpenBrace(); + + OutGeneratedCodeAttribute(); + OutLn($"file static class {className}"); + OutOpenBrace(); + + var staticValidationAttributes = staticFields + .OrderBy(x => x.FieldOrder) + .ToArray(); + + for (var i = 0; i < staticValidationAttributes.Length; i++) + { + var attributeInstance = staticValidationAttributes[i]; + OutIndent(); + Out($"internal static readonly {attributeInstance.FieldTypeFQN} {attributeInstance.FieldName} = "); + for (var j = 0; j < attributeInstance.InstantiationLines.Count; j++) + { + var line = attributeInstance.InstantiationLines[j]; + Out(line); + if (j != attributeInstance.InstantiationLines.Count - 1) + { + OutLn(); + OutIndent(); + } + else + { + Out(';'); + } + } + + OutLn(); + + if (i != staticValidationAttributes.Length - 1) + { + OutLn(); + } + } + + OutCloseBrace(); + + OutCloseBrace(); + } + + private void GenModelSelfValidationIfNecessary(ValidatedModel modelToValidate) + { + if (modelToValidate.SelfValidates) + { + OutLn($"builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context));"); + OutLn(); + } + } + + private void GenModelValidationMethod( + ValidatedModel modelToValidate, + bool makeStatic, + ref Dictionary staticValidationAttributesDict, + ref Dictionary staticValidatorsDict) + { + OutLn($"/// "); + OutLn($"/// Validates a specific named options instance (or all when is )."); + OutLn($"/// "); + OutLn($"/// The name of the options instance being validated."); + OutLn($"/// The options instance."); + OutLn($"/// Validation result."); + OutGeneratedCodeAttribute(); + + OutLn($"public {(makeStatic ? "static " : string.Empty)}global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, {modelToValidate.Name} options)"); + OutOpenBrace(); + OutLn($"var baseName = (string.IsNullOrEmpty(name) ? \"{modelToValidate.SimpleName}\" : name) + \".\";"); + OutLn($"var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();"); + OutLn($"var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);"); + OutLn(); + + foreach (var vm in modelToValidate.MembersToValidate) + { + if (vm.ValidationAttributes.Count > 0) + { + GenMemberValidation(vm, ref staticValidationAttributesDict); + OutLn(); + } + + if (vm.TransValidatorType != null) + { + GenTransitiveValidation(vm, ref staticValidatorsDict); + OutLn(); + } + + if (vm.EnumerationValidatorType != null) + { + GenEnumerationValidation(vm, ref staticValidatorsDict); + OutLn(); + } + } + + GenModelSelfValidationIfNecessary(modelToValidate); + OutLn($"return builder.Build();"); + OutCloseBrace(); + } + + private void GenMemberValidation(ValidatedMember vm, + ref Dictionary staticValidationAttributesDict) + { + OutLn($"context.MemberName = \"{vm.Name}\";"); + OutLn($"context.DisplayName = baseName + \"{vm.Name}\";"); + + foreach (var attr in vm.ValidationAttributes) + { + var staticValidationAttributeInstance = GetOrAddStaticValidationAttribute(ref staticValidationAttributesDict, attr); + + OutLn($"builder.AddResult({StaticValidationAttributeHolderClassFQN}.{staticValidationAttributeInstance.FieldName}.GetValidationResult(options.{vm.Name}, context));"); + } + } + + private StaticFieldInfo GetOrAddStaticValidationAttribute(ref Dictionary staticValidationAttributesDict, ValidationAttributeInfo attr) + { + var attrInstantiationStatementLines = new List(); + + if (attr.ConstructorArguments.Count > 0) + { + attrInstantiationStatementLines.Add($"new {attr.AttributeName}("); + + for (var i = 0; i < attr.ConstructorArguments.Count; i++) + { + if (i != attr.ConstructorArguments.Count - 1) + { + attrInstantiationStatementLines.Add($"{GetPaddingString(1)}{attr.ConstructorArguments[i]},"); + } + else + { + attrInstantiationStatementLines.Add($"{GetPaddingString(1)}{attr.ConstructorArguments[i]})"); + } + } + } + else + { + attrInstantiationStatementLines.Add($"new {attr.AttributeName}()"); + } + + if (attr.Properties.Count > 0) + { + attrInstantiationStatementLines.Add("{"); + + var propertiesOrderedByKey = attr.Properties + .OrderBy(p => p.Key) + .ToArray(); + + for (var i = 0; i < propertiesOrderedByKey.Length; i++) + { + var prop = propertiesOrderedByKey[i]; + var notLast = i != propertiesOrderedByKey.Length - 1; + attrInstantiationStatementLines.Add($"{GetPaddingString(1)}{prop.Key} = {prop.Value}{(notLast ? "," : string.Empty)}"); + } + + attrInstantiationStatementLines.Add("}"); + } + + var instantiationStatement = string.Join(Environment.NewLine, attrInstantiationStatementLines); + + if (!staticValidationAttributesDict.TryGetValue(instantiationStatement, out var staticValidationAttributeInstance)) + { + var fieldNumber = staticValidationAttributesDict.Count + 1; + staticValidationAttributeInstance = new StaticFieldInfo( + FieldTypeFQN: attr.AttributeName, + FieldOrder: fieldNumber, + FieldName: $"A{fieldNumber}", + InstantiationLines: attrInstantiationStatementLines); + + staticValidationAttributesDict.Add(instantiationStatement, staticValidationAttributeInstance); + } + + return staticValidationAttributeInstance; + } + + private void GenTransitiveValidation(ValidatedMember vm, ref Dictionary staticValidatorsDict) + { + string callSequence; + if (vm.TransValidateTypeIsSynthetic) + { + callSequence = vm.TransValidatorType!; + } + else + { + var staticValidatorInstance = GetOrAddStaticValidator(ref staticValidatorsDict, vm.TransValidatorType!); + + callSequence = $"{StaticValidatorHolderClassFQN}.{staticValidatorInstance.FieldName}"; + } + + var valueAccess = (vm.IsNullable && vm.IsValueType) ? ".Value" : string.Empty; + + if (vm.IsNullable) + { + OutLn($"if (options.{vm.Name} != null)"); + OutLn($"{{"); + OutLn($" builder.AddResult({callSequence}.Validate(baseName + \"{vm.Name}\", options.{vm.Name}{valueAccess}));"); + OutLn($"}}"); + } + else + { + OutLn($"builder.AddResult({callSequence}.Validate(baseName + \"{vm.Name}\", options.{vm.Name}{valueAccess}));"); + } + } + + private void GenEnumerationValidation(ValidatedMember vm, ref Dictionary staticValidatorsDict) + { + var valueAccess = (vm.IsValueType && vm.IsNullable) ? ".Value" : string.Empty; + var enumeratedValueAccess = (vm.EnumeratedIsNullable && vm.EnumeratedIsValueType) ? ".Value" : string.Empty; + string callSequence; + if (vm.EnumerationValidatorTypeIsSynthetic) + { + callSequence = vm.EnumerationValidatorType!; + } + else + { + var staticValidatorInstance = GetOrAddStaticValidator(ref staticValidatorsDict, vm.EnumerationValidatorType!); + + callSequence = $"{StaticValidatorHolderClassFQN}.{staticValidatorInstance.FieldName}"; + } + + if (vm.IsNullable) + { + OutLn($"if (options.{vm.Name} != null)"); + } + + OutOpenBrace(); + + OutLn($"var count = 0;"); + OutLn($"foreach (var o in options.{vm.Name}{valueAccess})"); + OutOpenBrace(); + + if (vm.EnumeratedIsNullable) + { + OutLn($"if (o is not null)"); + OutLn($"{{"); + OutLn($" builder.AddResult({callSequence}.Validate(baseName + $\"{vm.Name}[{{count++}}]\", o{enumeratedValueAccess}));"); + OutLn($"}}"); + + if (!vm.EnumeratedMayBeNull) + { + OutLn($"else"); + OutLn($"{{"); + OutLn($" builder.AddError(baseName + $\"{vm.Name}[{{count++}}] is null\");"); + OutLn($"}}"); + } + } + else + { + OutLn($"builder.AddResult({callSequence}.Validate(baseName + $\"{vm.Name}[{{count++}}]\", o{enumeratedValueAccess}));"); + } + + OutCloseBrace(); + OutCloseBrace(); + } + + #pragma warning disable CA1822 // Mark members as static: static should come before non-static, but we want the method to be here + private StaticFieldInfo GetOrAddStaticValidator(ref Dictionary staticValidatorsDict, string validatorTypeFQN) + #pragma warning restore CA1822 + { + if (!staticValidatorsDict.TryGetValue(validatorTypeFQN, out var staticValidatorInstance)) + { + var fieldNumber = staticValidatorsDict.Count + 1; + staticValidatorInstance = new StaticFieldInfo( + FieldTypeFQN: validatorTypeFQN, + FieldOrder: fieldNumber, + FieldName: $"V{fieldNumber}", + InstantiationLines: new[] { $"new {validatorTypeFQN}()" }); + + staticValidatorsDict.Add(validatorTypeFQN, staticValidatorInstance); + } + + return staticValidatorInstance; + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs b/src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs new file mode 100644 index 0000000000000..3243038427c0a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs @@ -0,0 +1,101 @@ +// 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.Generic; +using System.Text; + +namespace Microsoft.Extensions.Options.Generators +{ + internal class EmitterBase + { + private const int DefaultStringBuilderCapacity = 1024; + private const int IndentChars = 4; + + private readonly StringBuilder _sb = new(DefaultStringBuilderCapacity); + private readonly string[] _padding = new string[16]; + private int _indent; + + public EmitterBase(bool emitPreamble = true) + { + var padding = _padding; + for (int i = 0; i < padding.Length; i++) + { + padding[i] = new string(' ', i * IndentChars); + } + + if (emitPreamble) + { + Out(GeneratorUtilities.FilePreamble); + } + } + + protected void OutOpenBrace() + { + OutLn("{"); + Indent(); + } + + protected void OutCloseBrace() + { + Unindent(); + OutLn("}"); + } + + protected void OutCloseBraceWithExtra(string extra) + { + Unindent(); + OutIndent(); + Out("}"); + Out(extra); + OutLn(); + } + + protected void OutIndent() + { + _ = _sb.Append(_padding[_indent]); + } + + protected string GetPaddingString(byte indent) + { + return _padding[indent]; + } + + protected void OutLn() + { + _ = _sb.AppendLine(); + } + + protected void OutLn(string line) + { + OutIndent(); + _ = _sb.AppendLine(line); + } + + protected void OutPP(string line) + { + _ = _sb.AppendLine(line); + } + + protected void OutEnumeration(IEnumerable e) + { + bool first = true; + foreach (var item in e) + { + if (!first) + { + Out(", "); + } + + Out(item); + first = false; + } + } + + protected void Out(string text) => _ = _sb.Append(text); + protected void Out(char ch) => _ = _sb.Append(ch); + protected void Indent() => _indent++; + protected void Unindent() => _indent--; + protected void OutGeneratedCodeAttribute() => OutLn($"[{GeneratorUtilities.GeneratedCodeAttribute}]"); + protected string Capture() => _sb.ToString(); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs b/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs new file mode 100644 index 0000000000000..d1e01d3583e18 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs @@ -0,0 +1,47 @@ +// 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.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.Extensions.Options.Generators +{ + [Generator] + public class Generator : IIncrementalGenerator + { + private static readonly HashSet _attributeNames = new() + { + SymbolLoader.OptionsValidatorAttribute, + }; + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + GeneratorUtilities.Initialize(context, _attributeNames, HandleAnnotatedTypes); + } + + private static void HandleAnnotatedTypes(Compilation compilation, IEnumerable nodes, SourceProductionContext context) + { + if (!SymbolLoader.TryLoad(compilation, out var symbolHolder)) + { + // Not eligible compilation + return; + } + + var parser = new Parser(compilation, context.ReportDiagnostic, symbolHolder!, context.CancellationToken); + + var validatorTypes = parser.GetValidatorTypes(nodes.OfType()); + if (validatorTypes.Count > 0) + { + var emitter = new Emitter(); + var result = emitter.Emit(validatorTypes, context.CancellationToken); + + context.AddSource("Validators.g.cs", SourceText.From(result, Encoding.UTF8)); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs b/src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs new file mode 100644 index 0000000000000..9b8c3aaf8e59b --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs @@ -0,0 +1,131 @@ +// 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 Microsoft.CodeAnalysis; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Threading; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Extensions.Options.Generators +{ + internal static class GeneratorUtilities + { + public static string GeneratedCodeAttribute { get; } = $"global::System.CodeDom.Compiler.GeneratedCodeAttribute(" + + $"\"{typeof(GeneratorUtilities).Assembly.GetName().Name}\", " + + $"\"{typeof(GeneratorUtilities).Assembly.GetName().Version}\")"; + + public static string FilePreamble { get; } = @$" + // + #nullable enable + #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 + "; + + public static void Initialize( + IncrementalGeneratorInitializationContext context, + HashSet fullyQualifiedAttributeNames, + Action, SourceProductionContext> process) => Initialize(context, fullyQualifiedAttributeNames, x => x, process); + + public static void Initialize( + IncrementalGeneratorInitializationContext context, + HashSet fullyQualifiedAttributeNames, + Func transform, + Action, SourceProductionContext> process) + { + // strip the namespace prefix and the Attribute suffix + var shortAttributeNames = new HashSet(); + foreach (var n in fullyQualifiedAttributeNames) + { + var index = n.LastIndexOf('.') + 1; + _ = shortAttributeNames.Add(n.Substring(index, n.Length - index - "Attribute".Length)); + } + + var declarations = context.SyntaxProvider + .CreateSyntaxProvider( + (node, _) => Predicate(node, shortAttributeNames), + (gsc, ct) => Filter(gsc, fullyQualifiedAttributeNames, transform, ct)) + .Where(t => t is not null) + .Select((t, _) => t!); + + var compilationAndTypes = context.CompilationProvider.Combine(declarations.Collect()); + + context.RegisterSourceOutput(compilationAndTypes, (spc, source) => + { + var compilation = source.Left; + var nodes = source.Right; + + if (nodes.IsDefaultOrEmpty) + { + // nothing to do yet + return; + } + + process(compilation, nodes.Distinct(), spc); + }); + + static bool Predicate(SyntaxNode node, HashSet shortAttributeNames) + { + if (node.IsKind(SyntaxKind.Attribute)) + { + var attr = (AttributeSyntax)node; + + // see if we can trivially reject this node and avoid further work + if (attr.Name is IdentifierNameSyntax id) + { + return shortAttributeNames.Contains(id.Identifier.Text); + } + + // too complicated to check further, the filter will have to decide + return true; + } + + return false; + } + + static SyntaxNode? Filter(GeneratorSyntaxContext context, HashSet fullyQualifiedAttributeNames, Func transform, CancellationToken cancellationToken) + { + var attributeSyntax = (AttributeSyntax)context.Node; + + var ctor = context.SemanticModel.GetSymbolInfo(attributeSyntax, cancellationToken).Symbol as IMethodSymbol; + var attributeType = ctor?.ContainingType; + if (attributeType != null && fullyQualifiedAttributeNames.Contains(GetAttributeDisplayName(attributeType))) + { + var node = attributeSyntax.Parent?.Parent; + if (node != null) + { + return transform(node); + } + } + + return null; + } + + static string GetAttributeDisplayName(INamedTypeSymbol attributeType) + => attributeType.IsGenericType ? + attributeType.OriginalDefinition.ToDisplayString() : + attributeType.ToDisplayString(); + } + + /// + /// Reports will not be generated during design time to prevent file being written on every keystroke in VS. + /// References: + /// 1. + /// Design-time build. + /// 2. + /// Reading MSBuild Properties in Source Generators. + /// + /// . + /// The name of the MSBuild property that determines whether to produce a report. + /// bool value to indicate if reports should be generated. + public static bool ShouldGenerateReport(GeneratorExecutionContext context, string msBuildProperty) + { + _ = context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(msBuildProperty, out var generateFiles); + + return string.Equals(generateFiles, bool.TrueString, StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj new file mode 100644 index 0000000000000..602c547dedee2 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj @@ -0,0 +1,36 @@ + + + netstandard2.0 + false + false + true + cs + true + 4.4 + $(MicrosoftCodeAnalysisVersion_4_4) + $(DefineConstants);ROSLYN4_4_OR_GREATER + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedMember.cs b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedMember.cs new file mode 100644 index 0000000000000..cfed013591674 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedMember.cs @@ -0,0 +1,20 @@ +// 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.Generic; + +namespace Microsoft.Extensions.Options.Generators +{ + internal sealed record class ValidatedMember( + string Name, + List ValidationAttributes, + string? TransValidatorType, + bool TransValidateTypeIsSynthetic, + string? EnumerationValidatorType, + bool EnumerationValidatorTypeIsSynthetic, + bool IsNullable, + bool IsValueType, + bool EnumeratedIsNullable, + bool EnumeratedIsValueType, + bool EnumeratedMayBeNull); +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedModel.cs b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedModel.cs new file mode 100644 index 0000000000000..0d40d930051b1 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatedModel.cs @@ -0,0 +1,13 @@ +// 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.Generic; + +namespace Microsoft.Extensions.Options.Generators +{ + internal sealed record class ValidatedModel( + string Name, + string SimpleName, + bool SelfValidates, + List MembersToValidate); +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidationAttributeInfo.cs b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidationAttributeInfo.cs new file mode 100644 index 0000000000000..419ceca3e1d29 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidationAttributeInfo.cs @@ -0,0 +1,13 @@ +// 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.Generic; + +namespace Microsoft.Extensions.Options.Generators +{ + internal sealed record class ValidationAttributeInfo(string AttributeName) + { + public List ConstructorArguments { get; } = new(); + public Dictionary Properties { get; } = new(); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatorType.cs b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatorType.cs new file mode 100644 index 0000000000000..e104322c072ea --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Model/ValidatorType.cs @@ -0,0 +1,16 @@ +// 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.Generic; + +namespace Microsoft.Extensions.Options.Generators +{ + internal sealed record class ValidatorType( + string Namespace, + string Name, + string NameWithoutGenerics, + string DeclarationKeyword, + List ParentTypes, + bool IsSynthetic, + IList ModelsToValidate); +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs new file mode 100644 index 0000000000000..92bd403dd0214 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs @@ -0,0 +1,663 @@ +// 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.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Extensions.Options.Generators +{ + /// + /// Holds an internal parser class that extracts necessary information for generating IValidateOptions. + /// + internal sealed class Parser + { + private const int NumValidationMethodArgs = 2; + + private readonly CancellationToken _cancellationToken; + private readonly Compilation _compilation; + private readonly Action _reportDiagnostic; + private readonly SymbolHolder _symbolHolder; + private readonly Dictionary _synthesizedValidators = new(SymbolEqualityComparer.Default); + private readonly HashSet _visitedModelTypes = new(SymbolEqualityComparer.Default); + + public Parser( + Compilation compilation, + Action reportDiagnostic, + SymbolHolder symbolHolder, + CancellationToken cancellationToken) + { + _compilation = compilation; + _cancellationToken = cancellationToken; + _reportDiagnostic = reportDiagnostic; + _symbolHolder = symbolHolder; + } + + public IReadOnlyList GetValidatorTypes(IEnumerable classes) + { + var results = new List(); + + foreach (var group in classes.GroupBy(x => x.SyntaxTree)) + { + SemanticModel? sm = null; + foreach (var typeDec in group) + { + _cancellationToken.ThrowIfCancellationRequested(); + sm ??= _compilation.GetSemanticModel(typeDec.SyntaxTree); + + var validatorType = sm.GetDeclaredSymbol(typeDec) as ITypeSymbol; + if (validatorType != null) + { + if (validatorType.IsStatic) + { + Diag(DiagDescriptors.CantBeStaticClass, typeDec.GetLocation()); + continue; + } + + _visitedModelTypes.Clear(); + + var modelTypes = GetModelTypes(validatorType); + if (modelTypes.Count == 0) + { + // validator doesn't implement IValidateOptions + Diag(DiagDescriptors.DoesntImplementIValidateOptions, typeDec.GetLocation(), validatorType.Name); + continue; + } + + var modelsValidatorTypeValidates = new List(modelTypes.Count); + + foreach (var modelType in modelTypes) + { + if (modelType.Kind == SymbolKind.ErrorType) + { + // the compiler will report this error for us + continue; + } + else + { + // keep track of the models we look at, to detect loops + _ = _visitedModelTypes.Add(modelType.WithNullableAnnotation(NullableAnnotation.None)); + } + + if (AlreadyImplementsValidateMethod(validatorType, modelType)) + { + // this type already implements a validation function, we can't auto-generate a new one + Diag(DiagDescriptors.AlreadyImplementsValidateMethod, typeDec.GetLocation(), validatorType.Name); + continue; + } + + var membersToValidate = GetMembersToValidate(modelType, true); + if (membersToValidate.Count == 0) + { + // this type lacks any eligible members + Diag(DiagDescriptors.NoEligibleMembersFromValidator, typeDec.GetLocation(), modelType.ToString(), validatorType.ToString()); + continue; + } + + modelsValidatorTypeValidates.Add(new ValidatedModel( + GetFQN(modelType), + modelType.Name, + ModelSelfValidates(modelType), + membersToValidate)); + } + + string keyword = GetTypeKeyword(validatorType); + + // following code establishes the containment hierarchy for the generated type in terms of nested types + + var parents = new List(); + var parent = typeDec.Parent as TypeDeclarationSyntax; + + while (parent != null && IsAllowedKind(parent.Kind())) + { + parents.Add($"partial {GetTypeKeyword(parent)} {parent.Identifier}{parent.TypeParameterList} {parent.ConstraintClauses}"); + parent = parent.Parent as TypeDeclarationSyntax; + } + + parents.Reverse(); + + results.Add(new ValidatorType( + validatorType.ContainingNamespace.IsGlobalNamespace ? string.Empty : validatorType.ContainingNamespace.ToString(), + GetMinimalFQN(validatorType), + GetMinimalFQNWithoutGenerics(validatorType), + keyword, + parents, + false, + modelsValidatorTypeValidates)); + } + } + } + + results.AddRange(_synthesizedValidators.Values); + _synthesizedValidators.Clear(); + + return results; + } + + private static bool IsAllowedKind(SyntaxKind kind) => + kind == SyntaxKind.ClassDeclaration || + kind == SyntaxKind.StructDeclaration || + kind == SyntaxKind.RecordStructDeclaration || + kind == SyntaxKind.RecordDeclaration; + + private static string GetTypeKeyword(ITypeSymbol type) + { + if (type.IsReferenceType) + { + return type.IsRecord ? "record class" : "class"; + } + + return type.IsRecord ? "record struct" : "struct"; + } + + private static string GetTypeKeyword(TypeDeclarationSyntax type) => + type.Kind() switch + { + SyntaxKind.ClassDeclaration => "class", + SyntaxKind.RecordDeclaration => "record class", + SyntaxKind.RecordStructDeclaration => "record struct", + _ => type.Keyword.ValueText, + }; + + private static string GetFQN(ISymbol type) + => type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier)); + + private static string GetMinimalFQN(ISymbol type) + => type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeParameters)); + + private static string GetMinimalFQNWithoutGenerics(ISymbol type) + => type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat.WithGenericsOptions(SymbolDisplayGenericsOptions.None)); + + /// + /// Checks whether the given validator already implement the IValidationOptions>T< interface. + /// + private static bool AlreadyImplementsValidateMethod(INamespaceOrTypeSymbol validatorType, ISymbol modelType) + => validatorType + .GetMembers("Validate") + .Where(m => m.Kind == SymbolKind.Method) + .Select(m => (IMethodSymbol)m) + .Any(m => m.Parameters.Length == NumValidationMethodArgs + && m.Parameters[0].Type.SpecialType == SpecialType.System_String + && SymbolEqualityComparer.Default.Equals(m.Parameters[1].Type, modelType)); + + /// + /// Checks whether the given type contain any unbound generic type arguments. + /// + private static bool HasOpenGenerics(ITypeSymbol type, out string genericType) + { + if (type is INamedTypeSymbol mt) + { + if (mt.IsGenericType) + { + foreach (var ta in mt.TypeArguments) + { + if (ta.TypeKind == TypeKind.TypeParameter) + { + genericType = ta.Name; + return true; + } + } + } + } + else if (type is ITypeParameterSymbol) + { + genericType = type.Name; + return true; + } + else if (type is IArrayTypeSymbol ats) + { + return HasOpenGenerics(ats.ElementType, out genericType); + } + + genericType = string.Empty; + return false; + } + + private ITypeSymbol? GetEnumeratedType(ITypeSymbol type) + { + if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) + { + // extract the T from a Nullable + type = ((INamedTypeSymbol)type).TypeArguments[0]; + } + + foreach (var implementingInterface in type.AllInterfaces) + { + if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T))) + { + return implementingInterface.TypeArguments.First(); + } + } + + return null; + } + + private List GetMembersToValidate(ITypeSymbol modelType, bool speculate) + { + // make a list of the most derived members in the model type + + if (modelType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) + { + // extract the T from a Nullable + modelType = ((INamedTypeSymbol)modelType).TypeArguments[0]; + } + + var members = modelType.GetMembers().ToList(); + var addedMembers = new HashSet(members.Select(m => m.Name)); + var baseType = modelType.BaseType; + while (baseType is not null && baseType.SpecialType != SpecialType.System_Object) + { + var baseMembers = baseType.GetMembers().Where(m => !addedMembers.Contains(m.Name)); + members.AddRange(baseMembers); + addedMembers.UnionWith(baseMembers.Select(m => m.Name)); + baseType = baseType.BaseType; + } + + var membersToValidate = new List(); + foreach (var member in members) + { + var memberInfo = GetMemberInfo(member, speculate); + if (memberInfo != null) + { + if (member.DeclaredAccessibility != Accessibility.Public && member.DeclaredAccessibility != Accessibility.Internal) + { + Diag(DiagDescriptors.MemberIsInaccessible, member.Locations.First(), member.Name); + continue; + } + + membersToValidate.Add(memberInfo); + } + } + + return membersToValidate; + } + + private ValidatedMember? GetMemberInfo(ISymbol member, bool speculate) + { + ITypeSymbol memberType; + switch (member) + { + case IPropertySymbol prop: + memberType = prop.Type; + break; + case IFieldSymbol field: + if (field.AssociatedSymbol != null) + { + // a backing field for a property, don't need those + return null; + } + + memberType = field.Type; + break; + default: + // we only care about properties and fields + return null; + } + + var validationAttrs = new List(); + string? transValidatorTypeName = null; + string? enumerationValidatorTypeName = null; + var enumeratedIsNullable = false; + var enumeratedIsValueType = false; + var enumeratedMayBeNull = false; + var transValidatorIsSynthetic = false; + var enumerationValidatorIsSynthetic = false; + + foreach (var attribute in member.GetAttributes().Where(a => a.AttributeClass != null)) + { + var attributeType = attribute.AttributeClass!; + var attrLoc = attribute.ApplicationSyntaxReference?.GetSyntax().GetLocation(); + + if (SymbolEqualityComparer.Default.Equals(attributeType, _symbolHolder.ValidateObjectMembersAttributeSymbol)) + { + if (HasOpenGenerics(memberType, out var genericType)) + { + Diag(DiagDescriptors.CantUseWithGenericTypes, attrLoc, genericType); + #pragma warning disable S1226 // Method parameters, caught exceptions and foreach variables' initial values should not be ignored + speculate = false; + #pragma warning restore S1226 // Method parameters, caught exceptions and foreach variables' initial values should not be ignored + continue; + } + + if (attribute.ConstructorArguments.Length == 1) + { + var transValidatorType = attribute.ConstructorArguments[0].Value as INamedTypeSymbol; + if (transValidatorType != null) + { + if (CanValidate(transValidatorType, memberType)) + { + if (transValidatorType.Constructors.Where(c => !c.Parameters.Any()).Any()) + { + transValidatorTypeName = transValidatorType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + } + else + { + Diag(DiagDescriptors.ValidatorsNeedSimpleConstructor, attrLoc, transValidatorType.Name); + } + } + else + { + Diag(DiagDescriptors.DoesntImplementIValidateOptions, attrLoc, transValidatorType.Name, memberType.Name); + } + } + else + { + Diag(DiagDescriptors.NullValidatorType, attrLoc); + } + } + else if (!_visitedModelTypes.Add(memberType.WithNullableAnnotation(NullableAnnotation.None))) + { + Diag(DiagDescriptors.CircularTypeReferences, attrLoc, memberType.ToString()); + speculate = false; + continue; + } + + if (transValidatorTypeName == null) + { + transValidatorIsSynthetic = true; + transValidatorTypeName = AddSynthesizedValidator(memberType, member); + } + + // pop the stack + _ = _visitedModelTypes.Remove(memberType.WithNullableAnnotation(NullableAnnotation.None)); + } + else if (SymbolEqualityComparer.Default.Equals(attributeType, _symbolHolder.ValidateEnumeratedItemsAttributeSymbol)) + { + var enumeratedType = GetEnumeratedType(memberType); + if (enumeratedType == null) + { + Diag(DiagDescriptors.NotEnumerableType, attrLoc, memberType); + speculate = false; + continue; + } + + enumeratedIsNullable = enumeratedType.IsReferenceType || enumeratedType.NullableAnnotation == NullableAnnotation.Annotated; + enumeratedIsValueType = enumeratedType.IsValueType; + enumeratedMayBeNull = enumeratedType.NullableAnnotation == NullableAnnotation.Annotated; + + if (HasOpenGenerics(enumeratedType, out var genericType)) + { + Diag(DiagDescriptors.CantUseWithGenericTypes, attrLoc, genericType); + speculate = false; + continue; + } + + if (attribute.ConstructorArguments.Length == 1) + { + var enumerationValidatorType = attribute.ConstructorArguments[0].Value as INamedTypeSymbol; + if (enumerationValidatorType != null) + { + if (CanValidate(enumerationValidatorType, enumeratedType)) + { + if (enumerationValidatorType.Constructors.Where(c => c.Parameters.Length == 0).Any()) + { + enumerationValidatorTypeName = enumerationValidatorType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + } + else + { + Diag(DiagDescriptors.ValidatorsNeedSimpleConstructor, attrLoc, enumerationValidatorType.Name); + } + } + else + { + Diag(DiagDescriptors.DoesntImplementIValidateOptions, attrLoc, enumerationValidatorType.Name, enumeratedType.Name); + } + } + else + { + Diag(DiagDescriptors.NullValidatorType, attrLoc); + } + } + else if (!_visitedModelTypes.Add(enumeratedType.WithNullableAnnotation(NullableAnnotation.None))) + { + Diag(DiagDescriptors.CircularTypeReferences, attrLoc, enumeratedType.ToString()); + speculate = false; + continue; + } + + if (enumerationValidatorTypeName == null) + { + enumerationValidatorIsSynthetic = true; + enumerationValidatorTypeName = AddSynthesizedValidator(enumeratedType, member); + } + + // pop the stack + _ = _visitedModelTypes.Remove(enumeratedType.WithNullableAnnotation(NullableAnnotation.None)); + } + else if (DerivesFrom(attributeType, _symbolHolder.ValidationAttributeSymbol)) + { + var validationAttr = new ValidationAttributeInfo(attributeType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); + validationAttrs.Add(validationAttr); + + foreach (var constructorArgument in attribute.ConstructorArguments) + { + validationAttr.ConstructorArguments.Add(GetArgumentExpression(constructorArgument.Type!, constructorArgument.Value)); + } + + foreach (var namedArgument in attribute.NamedArguments) + { + validationAttr.Properties.Add(namedArgument.Key, GetArgumentExpression(namedArgument.Value.Type!, namedArgument.Value.Value)); + } + } + } + + // generate a warning if the field/property seems like it should be transitively validated + if (transValidatorTypeName == null && speculate && memberType.SpecialType == SpecialType.None) + { + if (!HasOpenGenerics(memberType, out var genericType)) + { + var membersToValidate = GetMembersToValidate(memberType, false); + if (membersToValidate.Count > 0) + { + Diag(DiagDescriptors.PotentiallyMissingTransitiveValidation, member.GetLocation(), memberType.Name, member.Name); + } + } + } + + // generate a warning if the field/property seems like it should be enumerated + if (enumerationValidatorTypeName == null && speculate) + { + var enumeratedType = GetEnumeratedType(memberType); + if (enumeratedType != null) + { + if (!HasOpenGenerics(enumeratedType, out var genericType)) + { + var membersToValidate = GetMembersToValidate(enumeratedType, false); + if (membersToValidate.Count > 0) + { + Diag(DiagDescriptors.PotentiallyMissingEnumerableValidation, member.GetLocation(), enumeratedType.Name, member.Name); + } + } + } + } + + if (validationAttrs.Count > 0 || transValidatorTypeName != null || enumerationValidatorTypeName != null) + { + return new( + member.Name, + validationAttrs, + transValidatorTypeName, + transValidatorIsSynthetic, + enumerationValidatorTypeName, + enumerationValidatorIsSynthetic, + memberType.IsReferenceType || memberType.NullableAnnotation == NullableAnnotation.Annotated, + memberType.IsValueType, + enumeratedIsNullable, + enumeratedIsValueType, + enumeratedMayBeNull); + } + + return null; + } + + private string? AddSynthesizedValidator(ITypeSymbol modelType, ISymbol member) + { + var mt = modelType.WithNullableAnnotation(NullableAnnotation.None); + if (mt.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) + { + // extract the T from a Nullable + mt = ((INamedTypeSymbol)mt).TypeArguments[0]; + } + + if (_synthesizedValidators.TryGetValue(mt, out var validator)) + { + return "global::" + validator.Namespace + "." + validator.Name; + } + + var membersToValidate = GetMembersToValidate(mt, true); + if (membersToValidate.Count == 0) + { + // this type lacks any eligible members + Diag(DiagDescriptors.NoEligibleMember, member.GetLocation(), mt.ToString(), member.ToString()); + return null; + } + + var model = new ValidatedModel( + GetFQN(mt), + mt.Name, + false, + membersToValidate); + + var validatorTypeName = "__" + mt.Name + "Validator__"; + + var result = new ValidatorType( + mt.ContainingNamespace.IsGlobalNamespace ? string.Empty : mt.ContainingNamespace.ToString(), + validatorTypeName, + validatorTypeName, + "class", + new List(), + true, + new[] { model }); + + _synthesizedValidators[mt] = result; + return "global::" + (result.Namespace.Length > 0 ? result.Namespace + "." + result.Name : result.Name); + } + + private bool DerivesFrom(ITypeSymbol source, ITypeSymbol dest) + { + var conversion = _compilation.ClassifyConversion(source, dest); + return conversion.IsReference && conversion.IsImplicit; + } + + private bool ModelSelfValidates(ITypeSymbol modelType) + { + foreach (var implementingInterface in modelType.AllInterfaces) + { + if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _symbolHolder.IValidatableObjectSymbol)) + { + return true; + } + } + + return false; + } + + private List GetModelTypes(ITypeSymbol validatorType) + { + var result = new List(); + foreach (var implementingInterface in validatorType.AllInterfaces) + { + if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _symbolHolder.ValidateOptionsSymbol)) + { + result.Add(implementingInterface.TypeArguments.First()); + } + } + + return result; + } + + private bool CanValidate(ITypeSymbol validatorType, ISymbol modelType) + { + foreach (var implementingInterface in validatorType.AllInterfaces) + { + if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _symbolHolder.ValidateOptionsSymbol)) + { + var t = implementingInterface.TypeArguments.First(); + if (SymbolEqualityComparer.Default.Equals(modelType, t)) + { + return true; + } + } + } + + return false; + } + + private string GetArgumentExpression(ITypeSymbol type, object? value) + { + if (value == null) + { + return "null"; + } + + if (type.SpecialType == SpecialType.System_Boolean) + { + return (bool)value ? "true" : "false"; + } + + if (SymbolEqualityComparer.Default.Equals(type, _symbolHolder.TypeSymbol) && + value is INamedTypeSymbol sym) + { + return $"typeof({sym.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)})"; + } + + if (type.SpecialType == SpecialType.System_String) + { + return $@"""{EscapeString(value.ToString())}"""; + } + + if (type.SpecialType == SpecialType.System_Char) + { + return $@"'{EscapeString(value.ToString())}'"; + } + + return $"({type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}){Convert.ToString(value, CultureInfo.InvariantCulture)}"; + } + + private static readonly char[] _specialChars = { '\n', '\r', '"', '\\' }; + + private static string EscapeString(string s) + { + int index = s.IndexOfAny(_specialChars); + if (index < 0) + { + return s; + } + + var sb = new StringBuilder(s.Length); + _ = sb.Append(s, 0, index); + + while (index < s.Length) + { + _ = s[index] switch + { + '\n' => sb.Append("\\n"), + '\r' => sb.Append("\\r"), + '"' => sb.Append("\\\""), + '\\' => sb.Append("\\\\"), + var other => sb.Append(other), + }; + + index++; + } + + return sb.ToString(); + } + + private void Diag(DiagnosticDescriptor desc, Location? location) + { + _reportDiagnostic(Diagnostic.Create(desc, location, Array.Empty())); + } + + private void Diag(DiagnosticDescriptor desc, Location? location, params object?[]? messageArgs) + { + _reportDiagnostic(Diagnostic.Create(desc, location, messageArgs)); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/ParserUtilities.cs b/src/libraries/Microsoft.Extensions.Options/gen/ParserUtilities.cs new file mode 100644 index 0000000000000..d79ad4cccb653 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/ParserUtilities.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Extensions.Options.Generators +{ + internal static class ParserUtilities + { + internal static AttributeData? GetSymbolAttributeAnnotationOrDefault(ISymbol? attribute, ISymbol symbol) + { + if (attribute is null) + { + return null; + } + + var attrs = symbol.GetAttributes(); + foreach (var item in attrs) + { + if (SymbolEqualityComparer.Default.Equals(attribute, item.AttributeClass) && item.AttributeConstructor != null) + { + return item; + } + } + + return null; + } + + internal static bool PropertyHasModifier(ISymbol property, SyntaxKind modifierToSearch, CancellationToken token) + => property + .DeclaringSyntaxReferences + .Any(x => + x.GetSyntax(token) is PropertyDeclarationSyntax syntax && + syntax.Modifiers.Any(m => m.IsKind(modifierToSearch))); + + internal static Location? GetLocation(this ISymbol symbol) + { + if (symbol is null) + { + return null; + } + + return symbol.Locations.IsDefaultOrEmpty + ? null + : symbol.Locations[0]; + } + + internal static bool IsBaseOrIdentity(ITypeSymbol source, ITypeSymbol dest, Compilation comp) + { + var conversion = comp.ClassifyConversion(source, dest); + return conversion.IsIdentity || (conversion.IsReference && conversion.IsImplicit); + } + + internal static bool ImplementsInterface(this ITypeSymbol type, ITypeSymbol interfaceType) + { + foreach (var iface in type.AllInterfaces) + { + if (SymbolEqualityComparer.Default.Equals(interfaceType, iface)) + { + return true; + } + } + + return false; + } + + // Check if parameter has either simplified (i.e. "int?") or explicit (Nullable) nullable type declaration: + internal static bool IsNullableOfT(this ITypeSymbol type) + => type.SpecialType == SpecialType.System_Nullable_T || type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T; + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources.resx b/src/libraries/Microsoft.Extensions.Options/gen/Resources.resx new file mode 100644 index 0000000000000..d9bae1523ae04 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources.resx @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Type {0} already implements the Validate method + + + A type already includes an implementation of the `Validate` method + + + [OptionsValidator] cannot be applied to static class {0} + + + `OptionsValidatorAttribute` can't be applied to a static class + + + 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 + + + There is a circular type reference involving type {0} preventing it from being used for static validation + + + Unsupported circular references in model types + + + Type {0} does not implement the required IValidateOptions<{1}> interface + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + Can't apply validation attributes to private field or property {0} + + + Can't validate private fields or properties + + + Type {0} has no fields or properties to validate, referenced from member {1} + + + Type {0} has no fields or properties to validate, referenced by type {1} + + + A type has no fields or properties to validate + + + A member type has no fields or properties to validate + + + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + + + Member type is not enumerable + + + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + + + Member potentially missing enumerable validation + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + + + Member potentially missing transitive validation + + + Validator type {0} doesn't have a parameterless constructor + + + Validators used for transitive or enumerable validation must have a constructor with no parameters + + diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx new file mode 100644 index 0000000000000..d9bae1523ae04 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Type {0} already implements the Validate method + + + A type already includes an implementation of the `Validate` method + + + [OptionsValidator] cannot be applied to static class {0} + + + `OptionsValidatorAttribute` can't be applied to a static class + + + 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 + + + There is a circular type reference involving type {0} preventing it from being used for static validation + + + Unsupported circular references in model types + + + Type {0} does not implement the required IValidateOptions<{1}> interface + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + Can't apply validation attributes to private field or property {0} + + + Can't validate private fields or properties + + + Type {0} has no fields or properties to validate, referenced from member {1} + + + Type {0} has no fields or properties to validate, referenced by type {1} + + + A type has no fields or properties to validate + + + A member type has no fields or properties to validate + + + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + + + Member type is not enumerable + + + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + + + Member potentially missing enumerable validation + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + + + Member potentially missing transitive validation + + + Validator type {0} doesn't have a parameterless constructor + + + 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.cs.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf new file mode 100644 index 0000000000000..57d16e1551253 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..5d004505ad1fe --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.de.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..608258bbfa7b4 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.es.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..0be945ff1400c --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.fr.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..a146a705363cd --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.it.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..e7fe4e78472e0 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ja.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..689728aa09597 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ko.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..6e7fd341996f1 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pl.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..e7b8a0f69064e --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pt-BR.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..9317984bebcaa --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ru.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..fa5feb3d2b603 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.tr.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..41f798ce9dd85 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hans.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000000000..04ac3af78908d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hant.xlf @@ -0,0 +1,137 @@ + + + + + + Type {0} already implements the Validate method + 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] cannot be applied to static class {0} + + + + `OptionsValidatorAttribute` can't be applied to a static class + `OptionsValidatorAttribute` can't be applied to a static class + + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + + There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface + + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + + Can't apply validation attributes to private field or property {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} + 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} + 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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 + + + + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Options/gen/SymbolHolder.cs b/src/libraries/Microsoft.Extensions.Options/gen/SymbolHolder.cs new file mode 100644 index 0000000000000..c78106e1bc4a2 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/SymbolHolder.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.Extensions.Options.Generators +{ + /// + /// Holds required symbols for the . + /// + internal sealed record class SymbolHolder( + INamedTypeSymbol OptionsValidatorSymbol, + INamedTypeSymbol ValidationAttributeSymbol, + INamedTypeSymbol DataTypeAttributeSymbol, + INamedTypeSymbol ValidateOptionsSymbol, + INamedTypeSymbol IValidatableObjectSymbol, + INamedTypeSymbol TypeSymbol, + INamedTypeSymbol? ValidateObjectMembersAttributeSymbol, + INamedTypeSymbol? ValidateEnumeratedItemsAttributeSymbol); +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/SymbolLoader.cs b/src/libraries/Microsoft.Extensions.Options/gen/SymbolLoader.cs new file mode 100644 index 0000000000000..6f805e91a0585 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/SymbolLoader.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.Extensions.Options.Generators +{ + internal static class SymbolLoader + { + public const string OptionsValidatorAttribute = "Microsoft.Extensions.Options.OptionsValidatorAttribute"; + internal const string ValidationAttribute = "System.ComponentModel.DataAnnotations.ValidationAttribute"; + internal const string DataTypeAttribute = "System.ComponentModel.DataAnnotations.DataTypeAttribute"; + internal const string IValidatableObjectType = "System.ComponentModel.DataAnnotations.IValidatableObject"; + internal const string IValidateOptionsType = "Microsoft.Extensions.Options.IValidateOptions`1"; + internal const string TypeOfType = "System.Type"; + internal const string ValidateObjectMembersAttribute = "Microsoft.Extensions.Options.ValidateObjectMembersAttribute"; + internal const string ValidateEnumeratedItemsAttribute = "Microsoft.Extensions.Options.ValidateEnumeratedItemsAttribute"; + + public static bool TryLoad(Compilation compilation, out SymbolHolder? symbolHolder) + { + INamedTypeSymbol? GetSymbol(string metadataName, bool optional = false) + { + var symbol = compilation.GetTypeByMetadataName(metadataName); + if (symbol == null && !optional) + { + return null; + } + + return symbol; + } + + // required + var optionsValidatorSymbol = GetSymbol(OptionsValidatorAttribute); + var validationAttributeSymbol = GetSymbol(ValidationAttribute); + var dataTypeAttributeSymbol = GetSymbol(DataTypeAttribute); + var ivalidatableObjectSymbol = GetSymbol(IValidatableObjectType); + var validateOptionsSymbol = GetSymbol(IValidateOptionsType); + var typeSymbol = GetSymbol(TypeOfType); + + #pragma warning disable S1067 // Expressions should not be too complex + if (optionsValidatorSymbol == null || + validationAttributeSymbol == null || + dataTypeAttributeSymbol == null || + ivalidatableObjectSymbol == null || + validateOptionsSymbol == null || + typeSymbol == null) + { + symbolHolder = default; + return false; + } + #pragma warning restore S1067 // Expressions should not be too complex + + symbolHolder = new( + optionsValidatorSymbol, + validationAttributeSymbol, + dataTypeAttributeSymbol, + validateOptionsSymbol, + ivalidatableObjectSymbol, + typeSymbol, + + // optional + GetSymbol(ValidateObjectMembersAttribute, optional: true), + GetSymbol(ValidateEnumeratedItemsAttribute, optional: true)); + + return true; + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/TypeDeclarationSyntaxReceiver.cs b/src/libraries/Microsoft.Extensions.Options/gen/TypeDeclarationSyntaxReceiver.cs new file mode 100644 index 0000000000000..f007c53cd5fc1 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/gen/TypeDeclarationSyntaxReceiver.cs @@ -0,0 +1,43 @@ +// 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.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Extensions.Options.Generators +{ + /// + /// Class/struct/record declaration syntax receiver for generators. + /// + internal sealed class TypeDeclarationSyntaxReceiver : ISyntaxReceiver + { + internal static ISyntaxReceiver Create() => new TypeDeclarationSyntaxReceiver(); + + /// + /// Gets class/struct/record declaration syntax holders after visiting nodes. + /// + public ICollection TypeDeclarations { get; } = new List(); + + /// + public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + { + if (syntaxNode is ClassDeclarationSyntax classSyntax) + { + TypeDeclarations.Add(classSyntax); + } + else if (syntaxNode is StructDeclarationSyntax structSyntax) + { + TypeDeclarations.Add(structSyntax); + } + else if (syntaxNode is RecordDeclarationSyntax recordSyntax) + { + TypeDeclarations.Add(recordSyntax); + } + else if (syntaxNode is InterfaceDeclarationSyntax interfaceSyntax) + { + TypeDeclarations.Add(interfaceSyntax); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/ref/Microsoft.Extensions.Options.cs b/src/libraries/Microsoft.Extensions.Options/ref/Microsoft.Extensions.Options.cs index 6ae6095e9ad3e..d81036040688b 100644 --- a/src/libraries/Microsoft.Extensions.Options/ref/Microsoft.Extensions.Options.cs +++ b/src/libraries/Microsoft.Extensions.Options/ref/Microsoft.Extensions.Options.cs @@ -215,6 +215,10 @@ public OptionsValidationException(string optionsName, System.Type optionsType, S public string OptionsName { get { throw null; } } public System.Type OptionsType { get { throw null; } } } + [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct)] + public sealed class OptionsValidatorAttribute : System.Attribute + { + } public partial class OptionsWrapper<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : Microsoft.Extensions.Options.IOptions where TOptions : class { public OptionsWrapper(TOptions options) { } @@ -282,6 +286,20 @@ public PostConfigureOptions(string? name, TDep1 dependency1, TDep2 dependency2, public virtual void PostConfigure(string? name, TOptions options) { } public void PostConfigure(TOptions options) { } } + [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field)] + public sealed class ValidateEnumeratedItemsAttribute : System.Attribute + { + public ValidateEnumeratedItemsAttribute() {} + public ValidateEnumeratedItemsAttribute(System.Type validator) { throw null; } + public System.Type? Validator { get {throw null; } } + } + [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field)] + public sealed class ValidateObjectMembersAttribute : System.Attribute + { + public ValidateObjectMembersAttribute() {} + public ValidateObjectMembersAttribute(System.Type validator) { throw null; } + public System.Type? Validator { get { throw null; } } + } public partial class ValidateOptionsResult { public static readonly Microsoft.Extensions.Options.ValidateOptionsResult Skip; diff --git a/src/libraries/Microsoft.Extensions.Options/src/OptionsValidatorAttribute.cs b/src/libraries/Microsoft.Extensions.Options/src/OptionsValidatorAttribute.cs new file mode 100644 index 0000000000000..39e6aa3c5b71e --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/src/OptionsValidatorAttribute.cs @@ -0,0 +1,16 @@ +// 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.Diagnostics; + +namespace Microsoft.Extensions.Options +{ + /// + /// Triggers the automatic generation of the implementation of at compile time. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] + public sealed class OptionsValidatorAttribute : Attribute + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/src/ValidateEnumeratedItemsAttribute.cs b/src/libraries/Microsoft.Extensions.Options/src/ValidateEnumeratedItemsAttribute.cs new file mode 100644 index 0000000000000..7f3630207e13a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/src/ValidateEnumeratedItemsAttribute.cs @@ -0,0 +1,45 @@ +// 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.Diagnostics.CodeAnalysis; +using Microsoft.Extensions.Options; + +namespace Microsoft.Extensions.Options +{ + /// + /// Marks a field or property to be enumerated, and each enumerated object to be validated. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] + public sealed class ValidateEnumeratedItemsAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Using this constructor for a field/property tells the code generator to + /// generate validation for the individual members of the enumerable's type. + /// + public ValidateEnumeratedItemsAttribute() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// A type that implements for the enumerable's type. + /// + /// Using this constructor for a field/property tells the code generator to use the given type to validate + /// the object held by the enumerable. + /// + public ValidateEnumeratedItemsAttribute(Type validator) + { + Validator = validator; + } + + /// + /// Gets the type to use to validate the enumerable's objects. + /// + public Type? Validator { get; } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/src/ValidateObjectMembersAttribute.cs b/src/libraries/Microsoft.Extensions.Options/src/ValidateObjectMembersAttribute.cs new file mode 100644 index 0000000000000..69a36cad65ede --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/src/ValidateObjectMembersAttribute.cs @@ -0,0 +1,44 @@ +// 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 Microsoft.Extensions.Options; + +namespace Microsoft.Extensions.Options +{ + /// + /// Marks a field or property to be validated transitively. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] + public sealed class ValidateObjectMembersAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Using this constructor for a field/property tells the code generator to + /// generate validation for the individual members of the field/property's type. + /// + public ValidateObjectMembersAttribute() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// A type that implements for the field/property's type. + /// + /// Using this constructor for a field/property tells the code generator to use the given type to validate + /// the object held by the field/property. + /// + public ValidateObjectMembersAttribute(Type validator) + { + Validator = validator; + } + + /// + /// Gets the type to use to validate a field or property. + /// + public Type? Validator { get; } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs new file mode 100644 index 0000000000000..137e626c2798b --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs @@ -0,0 +1,1756 @@ + + // + #nullable enable + #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 + #pragma warning disable CS0618 // Type or member is obsolete +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] +internal sealed partial class __ThirdModelNoNamespaceValidator__ +{ + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ThirdModelNoNamespace options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } +} +#pragma warning disable CS0618 // Type or member is obsolete +partial class FirstValidatorNoNamespace +{ + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FirstModelNoNamespace options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModelNoNamespace" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V1.Validate(baseName + "P2", options.P2)); + } + + if (options.P3 != null) + { + builder.AddResult(global::__ThirdModelNoNamespaceValidator__.Validate(baseName + "P3", options.P3)); + } + + return builder.Build(); + } +} +#pragma warning disable CS0618 // Type or member is obsolete +partial class SecondValidatorNoNamespace +{ + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SecondModelNoNamespace options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModelNoNamespace" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace CustomAttr +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::CustomAttr.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A3.GetValidationResult(options.P1, context)); + + context.MemberName = "P2"; + context.DisplayName = baseName + "P2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A4.GetValidationResult(options.P2, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Value"; + context.DisplayName = baseName + "Value"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A5.GetValidationResult(options.Value, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + if (options.P1 != null) + { + var count = 0; + foreach (var o in options.P1) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P1[{count++}] is null"); + } + } + } + + if (options.P2 != null) + { + var count = 0; + foreach (var o in options.P2) + { + if (o is not null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P2[{count++}] is null"); + } + } + } + + if (options.P3 != null) + { + var count = 0; + foreach (var o in options.P3) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count++}]", o)); + } + } + } + + if (options.P4 != null) + { + var count = 0; + foreach (var o in options.P4) + { + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P4[{count++}]", o)); + } + } + + if (options.P5 != null) + { + var count = 0; + foreach (var o in options.P5) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count++}]", o.Value)); + } + } + } + + if (options.P51 != null) + { + var count = 0; + foreach (var o in options.P51) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count++}]", o.Value)); + } + } + } + + if (options.P6 != null) + { + var count = 0; + foreach (var o in options.P6.Value) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P6[{count++}] is null"); + } + } + } + + { + var count = 0; + foreach (var o in options.P7) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P7[{count++}] is null"); + } + } + } + + if (options.P8 != null) + { + var count = 0; + foreach (var o in options.P8.Value) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P8[{count++}] is null"); + } + } + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + partial struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Fields +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Fields +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V3.Validate(baseName + "P2", options.P2)); + } + + builder.AddResult(global::Fields.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Fields +{ + partial struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace FileScopedNamespace +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FileScopedNamespace.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace FunnyStrings +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FunnyStrings.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A6.GetValidationResult(options.P1, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Generics +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Generics +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P3 != null) + { + builder.AddResult(global::Generics.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace MultiModelValidator +{ + partial struct MultiValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V4.Validate(baseName + "P2", options.P2)); + } + + return builder.Build(); + } + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P3"; + context.DisplayName = baseName + "P3"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P3, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial record struct Container7 + { + partial record struct FifthValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial class Container2 + { + partial class Container3 + { + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V5.Validate(baseName + "P2", options.P2)); + } + + builder.AddResult(global::Nested.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); + + if (options.P4 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V6.Validate(baseName + "P4", options.P4)); + } + + return builder.Build(); + } + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial struct Container6 + { + partial struct FourthValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial class Container2 + { + partial class Container3 + { + partial struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial record class Container4 + { + partial record class Container5 + { + partial struct ThirdValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RandomMembers +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RandomMembers.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + partial record struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V7.Validate(baseName + "P2", options.P2)); + } + + if (options.P3 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V8.Validate(baseName + "P3", options.P3)); + } + + builder.AddResult(global::RecordTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + partial record struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + partial record class ThirdValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RepeatedTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + + if (options.P4 != null) + { + builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RepeatedTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RepeatedTypes +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + + if (options.P1 != null) + { + builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P1", options.P1)); + } + + context.MemberName = "P2"; + context.DisplayName = baseName + "P2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P2, context)); + + if (options.P2 != null) + { + builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2)); + } + + context.MemberName = "P3"; + context.DisplayName = baseName + "P3"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); + + if (options.P3 != null) + { + builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace SelfValidation +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + + builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __RangeAttributeModelDoubleValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __RequiredAttributeModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __TypeWithoutOptionsValidatorValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.TypeWithoutOptionsValidator options) + { + var baseName = (string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val1"; + context.DisplayName = baseName + "Val1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); + + context.MemberName = "Val2"; + context.DisplayName = baseName + "Val2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val2, context)); + + if (options.YetAnotherComplexVal != null) + { + builder.AddResult(global::TestClasses.OptionsValidation.__RangeAttributeModelDoubleValidator__.Validate(baseName + "YetAnotherComplexVal", options.YetAnotherComplexVal)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class AttributePropertyModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.AttributePropertyModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "AttributePropertyModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val1"; + context.DisplayName = baseName + "Val1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A9.GetValidationResult(options.Val1, context)); + + context.MemberName = "Val2"; + context.DisplayName = baseName + "Val2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A10.GetValidationResult(options.Val2, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class ComplexModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.ComplexModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + if (options.ComplexVal != null) + { + builder.AddResult(global::TestClasses.OptionsValidation.__RequiredAttributeModelValidator__.Validate(baseName + "ComplexVal", options.ComplexVal)); + } + + if (options.ValWithoutOptionsValidator != null) + { + builder.AddResult(global::TestClasses.OptionsValidation.__TypeWithoutOptionsValidatorValidator__.Validate(baseName + "ValWithoutOptionsValidator", options.ValWithoutOptionsValidator)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class CustomTypeCustomValidationAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomTypeCustomValidationAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A11.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class CustomValidationAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomValidationAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A12.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class DataTypeAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DataTypeAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "DataTypeAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A13.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class DerivedModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DerivedModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "DerivedModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "DerivedVal"; + context.DisplayName = baseName + "DerivedVal"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + + context.MemberName = "VirtualValWithAttr"; + context.DisplayName = baseName + "VirtualValWithAttr"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithAttr, context)); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class EmailAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.EmailAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "EmailAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A14.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class LeafModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.LeafModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "LeafModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "VirtualValWithoutAttr"; + context.DisplayName = baseName + "VirtualValWithoutAttr"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithoutAttr, context)); + + context.MemberName = "DerivedVal"; + context.DisplayName = baseName + "DerivedVal"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class MultipleAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.MultipleAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "MultipleAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val1"; + context.DisplayName = baseName + "Val1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A15.GetValidationResult(options.Val1, context)); + + context.MemberName = "Val2"; + context.DisplayName = baseName + "Val2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val2, context)); + + context.MemberName = "Val3"; + context.DisplayName = baseName + "Val3"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A17.GetValidationResult(options.Val3, context)); + + context.MemberName = "Val4"; + context.DisplayName = baseName + "Val4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A18.GetValidationResult(options.Val4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RangeAttributeModelDateValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDate options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDate" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A19.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RangeAttributeModelDoubleValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RangeAttributeModelIntValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelInt options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelInt" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RegularExpressionAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RegularExpressionAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A20.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RequiredAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace ValueTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace ValueTypes +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2.Value)); + } + + builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); + + if (options.P4 != null) + { + builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P4", options.P4.Value)); + } + + return builder.Build(); + } + } +} +namespace __OptionValidationStaticInstances +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + file static class __Attributes + { + internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute(); + + internal static readonly global::System.ComponentModel.DataAnnotations.MinLengthAttribute A2 = new global::System.ComponentModel.DataAnnotations.MinLengthAttribute( + (int)5); + + internal static readonly global::CustomAttr.CustomAttribute A3 = new global::CustomAttr.CustomAttribute( + 'A', + true, + null); + + internal static readonly global::CustomAttr.CustomAttribute A4 = new global::CustomAttr.CustomAttribute( + 'A', + false, + "X"); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A5 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)0, + (int)10); + + internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A6 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute( + "\"\r\n\\\\"); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A7 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (double)0.5, + (double)0.9); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A8 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + typeof(global::System.DateTime), + "1/2/2004", + "3/4/2004"); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A9 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)1, + (int)3) + { + ErrorMessage = "ErrorMessage" + }; + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A10 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)1, + (int)3) + { + ErrorMessageResourceName = "ErrorMessageResourceName", + ErrorMessageResourceType = typeof(global::System.SR) + }; + + internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A11 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute( + typeof(global::TestClasses.OptionsValidation.CustomTypeCustomValidationTest), + "TestMethod"); + + internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A12 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute( + typeof(global::TestClasses.OptionsValidation.CustomValidationTest), + "TestMethod"); + + internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A13 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute( + (global::System.ComponentModel.DataAnnotations.DataType)7); + + internal static readonly global::System.ComponentModel.DataAnnotations.EmailAddressAttribute A14 = new global::System.ComponentModel.DataAnnotations.EmailAddressAttribute(); + + internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A15 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute( + (global::System.ComponentModel.DataAnnotations.DataType)11); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A16 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)1, + (int)3); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A17 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)3, + (int)5); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A18 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)5, + (int)9); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A19 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + typeof(global::System.DateTime), + "1/2/2004", + "3/4/2004") + { + ParseLimitsInInvariantCulture = true + }; + + internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A20 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute( + "\\s"); + } +} +namespace __OptionValidationStaticInstances +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + file static class __Validators + { + internal static readonly global::SecondValidatorNoNamespace V1 = new global::SecondValidatorNoNamespace(); + + internal static readonly global::Enumeration.SecondValidator V2 = new global::Enumeration.SecondValidator(); + + internal static readonly global::Fields.SecondValidator V3 = new global::Fields.SecondValidator(); + + internal static readonly global::MultiModelValidator.MultiValidator V4 = new global::MultiModelValidator.MultiValidator(); + + internal static readonly global::Nested.Container2.Container3.SecondValidator V5 = new global::Nested.Container2.Container3.SecondValidator(); + + internal static readonly global::Nested.Container4.Container5.ThirdValidator V6 = new global::Nested.Container4.Container5.ThirdValidator(); + + internal static readonly global::RecordTypes.SecondValidator V7 = new global::RecordTypes.SecondValidator(); + + internal static readonly global::RecordTypes.ThirdValidator V8 = new global::RecordTypes.ThirdValidator(); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs new file mode 100644 index 0000000000000..452bf9bd63fd8 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs @@ -0,0 +1,1748 @@ + + // + #nullable enable + #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 + #pragma warning disable CS0618 // Type or member is obsolete +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] +internal sealed partial class __ThirdModelNoNamespaceValidator__ +{ + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ThirdModelNoNamespace options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } +} +#pragma warning disable CS0618 // Type or member is obsolete +partial class FirstValidatorNoNamespace +{ + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FirstModelNoNamespace options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModelNoNamespace" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V1.Validate(baseName + "P2", options.P2)); + } + + if (options.P3 != null) + { + builder.AddResult(global::__ThirdModelNoNamespaceValidator__.Validate(baseName + "P3", options.P3)); + } + + return builder.Build(); + } +} +#pragma warning disable CS0618 // Type or member is obsolete +partial class SecondValidatorNoNamespace +{ + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SecondModelNoNamespace options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModelNoNamespace" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace CustomAttr +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::CustomAttr.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A3.GetValidationResult(options.P1, context)); + + context.MemberName = "P2"; + context.DisplayName = baseName + "P2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A4.GetValidationResult(options.P2, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Value"; + context.DisplayName = baseName + "Value"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A5.GetValidationResult(options.Value, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + if (options.P1 != null) + { + var count = 0; + foreach (var o in options.P1) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P1[{count++}] is null"); + } + } + } + + if (options.P2 != null) + { + var count = 0; + foreach (var o in options.P2) + { + if (o is not null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P2[{count++}] is null"); + } + } + } + + if (options.P3 != null) + { + var count = 0; + foreach (var o in options.P3) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count++}]", o)); + } + } + } + + if (options.P4 != null) + { + var count = 0; + foreach (var o in options.P4) + { + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P4[{count++}]", o)); + } + } + + if (options.P5 != null) + { + var count = 0; + foreach (var o in options.P5) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count++}]", o.Value)); + } + } + } + + if (options.P51 != null) + { + var count = 0; + foreach (var o in options.P51) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count++}]", o.Value)); + } + } + } + + if (options.P6 != null) + { + var count = 0; + foreach (var o in options.P6.Value) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P6[{count++}] is null"); + } + } + } + + { + var count = 0; + foreach (var o in options.P7) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P7[{count++}] is null"); + } + } + } + + if (options.P8 != null) + { + var count = 0; + foreach (var o in options.P8.Value) + { + if (o is not null) + { + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count++}]", o)); + } + else + { + builder.AddError(baseName + $"P8[{count++}] is null"); + } + } + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Enumeration +{ + partial struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Fields +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Fields +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V3.Validate(baseName + "P2", options.P2)); + } + + builder.AddResult(global::Fields.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Fields +{ + partial struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace FileScopedNamespace +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FileScopedNamespace.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace FunnyStrings +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FunnyStrings.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A6.GetValidationResult(options.P1, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Generics +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Generics +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P3 != null) + { + builder.AddResult(global::Generics.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace MultiModelValidator +{ + partial struct MultiValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V4.Validate(baseName + "P2", options.P2)); + } + + return builder.Build(); + } + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P3"; + context.DisplayName = baseName + "P3"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P3, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial record struct Container7 + { + partial record struct FifthValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial class Container2 + { + partial class Container3 + { + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V5.Validate(baseName + "P2", options.P2)); + } + + builder.AddResult(global::Nested.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); + + if (options.P4 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V6.Validate(baseName + "P4", options.P4)); + } + + return builder.Build(); + } + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial struct Container6 + { + partial struct FourthValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial class Container2 + { + partial class Container3 + { + partial struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace Nested +{ + partial record class Container4 + { + partial record class Container5 + { + partial struct ThirdValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RandomMembers +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RandomMembers.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P6"; + context.DisplayName = baseName + "P6"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + partial record struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V7.Validate(baseName + "P2", options.P2)); + } + + if (options.P3 != null) + { + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V8.Validate(baseName + "P3", options.P3)); + } + + builder.AddResult(global::RecordTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + partial record struct SecondValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RecordTypes +{ + partial record class ThirdValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RepeatedTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + + if (options.P4 != null) + { + builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RepeatedTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __ThirdModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.ThirdModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P5"; + context.DisplayName = baseName + "P5"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace RepeatedTypes +{ + partial class FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + + if (options.P1 != null) + { + builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P1", options.P1)); + } + + context.MemberName = "P2"; + context.DisplayName = baseName + "P2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P2, context)); + + if (options.P2 != null) + { + builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2)); + } + + context.MemberName = "P3"; + context.DisplayName = baseName + "P3"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); + + if (options.P3 != null) + { + builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace SelfValidation +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + + builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __RangeAttributeModelDoubleValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __RequiredAttributeModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __TypeWithoutOptionsValidatorValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.TypeWithoutOptionsValidator options) + { + var baseName = (string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val1"; + context.DisplayName = baseName + "Val1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); + + context.MemberName = "Val2"; + context.DisplayName = baseName + "Val2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val2, context)); + + if (options.YetAnotherComplexVal != null) + { + builder.AddResult(global::TestClasses.OptionsValidation.__RangeAttributeModelDoubleValidator__.Validate(baseName + "YetAnotherComplexVal", options.YetAnotherComplexVal)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class AttributePropertyModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.AttributePropertyModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "AttributePropertyModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val1"; + context.DisplayName = baseName + "Val1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A9.GetValidationResult(options.Val1, context)); + + context.MemberName = "Val2"; + context.DisplayName = baseName + "Val2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A10.GetValidationResult(options.Val2, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class ComplexModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.ComplexModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + if (options.ComplexVal != null) + { + builder.AddResult(global::TestClasses.OptionsValidation.__RequiredAttributeModelValidator__.Validate(baseName + "ComplexVal", options.ComplexVal)); + } + + if (options.ValWithoutOptionsValidator != null) + { + builder.AddResult(global::TestClasses.OptionsValidation.__TypeWithoutOptionsValidatorValidator__.Validate(baseName + "ValWithoutOptionsValidator", options.ValWithoutOptionsValidator)); + } + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class CustomTypeCustomValidationAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomTypeCustomValidationAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A11.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class CustomValidationAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomValidationAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A12.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class DataTypeAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DataTypeAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "DataTypeAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A13.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class DerivedModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DerivedModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "DerivedModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "DerivedVal"; + context.DisplayName = baseName + "DerivedVal"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + + context.MemberName = "VirtualValWithAttr"; + context.DisplayName = baseName + "VirtualValWithAttr"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithAttr, context)); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class EmailAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.EmailAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "EmailAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A14.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class LeafModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.LeafModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "LeafModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "VirtualValWithoutAttr"; + context.DisplayName = baseName + "VirtualValWithoutAttr"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithoutAttr, context)); + + context.MemberName = "DerivedVal"; + context.DisplayName = baseName + "DerivedVal"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class MultipleAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.MultipleAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "MultipleAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val1"; + context.DisplayName = baseName + "Val1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A15.GetValidationResult(options.Val1, context)); + + context.MemberName = "Val2"; + context.DisplayName = baseName + "Val2"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val2, context)); + + context.MemberName = "Val3"; + context.DisplayName = baseName + "Val3"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A17.GetValidationResult(options.Val3, context)); + + context.MemberName = "Val4"; + context.DisplayName = baseName + "Val4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A18.GetValidationResult(options.Val4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RangeAttributeModelDateValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDate options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDate" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RangeAttributeModelDoubleValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RangeAttributeModelIntValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelInt options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelInt" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RegularExpressionAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RegularExpressionAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A19.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace TestClasses.OptionsValidation +{ + partial class RequiredAttributeModelValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "Val"; + context.DisplayName = baseName + "Val"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace ValueTypes +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + internal sealed partial class __SecondModelValidator__ + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.SecondModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P4"; + context.DisplayName = baseName + "P4"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + + return builder.Build(); + } + } +} +#pragma warning disable CS0618 // Type or member is obsolete +namespace ValueTypes +{ + partial struct FirstValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.FirstModel options) + { + var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + + context.MemberName = "P1"; + context.DisplayName = baseName + "P1"; + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + + if (options.P2 != null) + { + builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2.Value)); + } + + builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); + + if (options.P4 != null) + { + builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P4", options.P4.Value)); + } + + return builder.Build(); + } + } +} +namespace __OptionValidationStaticInstances +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + file static class __Attributes + { + internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute(); + + internal static readonly global::System.ComponentModel.DataAnnotations.MinLengthAttribute A2 = new global::System.ComponentModel.DataAnnotations.MinLengthAttribute( + (int)5); + + internal static readonly global::CustomAttr.CustomAttribute A3 = new global::CustomAttr.CustomAttribute( + 'A', + true, + null); + + internal static readonly global::CustomAttr.CustomAttribute A4 = new global::CustomAttr.CustomAttribute( + 'A', + false, + "X"); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A5 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)0, + (int)10); + + internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A6 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute( + "\"\r\n\\\\"); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A7 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (double)0.5, + (double)0.9); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A8 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + typeof(global::System.DateTime), + "1/2/2004", + "3/4/2004"); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A9 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)1, + (int)3) + { + ErrorMessage = "ErrorMessage" + }; + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A10 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)1, + (int)3) + { + ErrorMessageResourceName = "ErrorMessageResourceName", + ErrorMessageResourceType = typeof(global::System.SR) + }; + + internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A11 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute( + typeof(global::TestClasses.OptionsValidation.CustomTypeCustomValidationTest), + "TestMethod"); + + internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A12 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute( + typeof(global::TestClasses.OptionsValidation.CustomValidationTest), + "TestMethod"); + + internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A13 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute( + (global::System.ComponentModel.DataAnnotations.DataType)7); + + internal static readonly global::System.ComponentModel.DataAnnotations.EmailAddressAttribute A14 = new global::System.ComponentModel.DataAnnotations.EmailAddressAttribute(); + + internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A15 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute( + (global::System.ComponentModel.DataAnnotations.DataType)11); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A16 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)1, + (int)3); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A17 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)3, + (int)5); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A18 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)5, + (int)9); + + internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A19 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute( + "\\s"); + } +} +namespace __OptionValidationStaticInstances +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + file static class __Validators + { + internal static readonly global::SecondValidatorNoNamespace V1 = new global::SecondValidatorNoNamespace(); + + internal static readonly global::Enumeration.SecondValidator V2 = new global::Enumeration.SecondValidator(); + + internal static readonly global::Fields.SecondValidator V3 = new global::Fields.SecondValidator(); + + internal static readonly global::MultiModelValidator.MultiValidator V4 = new global::MultiModelValidator.MultiValidator(); + + internal static readonly global::Nested.Container2.Container3.SecondValidator V5 = new global::Nested.Container2.Container3.SecondValidator(); + + internal static readonly global::Nested.Container4.Container5.ThirdValidator V6 = new global::Nested.Container4.Container5.ThirdValidator(); + + internal static readonly global::RecordTypes.SecondValidator V7 = new global::RecordTypes.SecondValidator(); + + internal static readonly global::RecordTypes.ThirdValidator V8 = new global::RecordTypes.ThirdValidator(); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs new file mode 100644 index 0000000000000..44134625cd6c0 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs @@ -0,0 +1,61 @@ +// 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.ComponentModel.DataAnnotations; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; +using SourceGenerators.Tests; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options.Generators; +using Microsoft.Shared.Data.Validation; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class EmitterTests +{ + [Fact] + public async Task TestEmitter() + { + var sources = new List(); +#pragma warning disable RS1035 // To allow using the File IO APIs inside the analyzer test + foreach (var file in Directory.GetFiles("TestClasses")) + { +#if NETCOREAPP3_1_OR_GREATER + sources.Add("#define NETCOREAPP3_1_OR_GREATER\n" + File.ReadAllText(file)); +#else + sources.Add(File.ReadAllText(file)); +#endif + } + + var (d, r) = await RoslynTestUtils.RunGenerator( + new Generator(), + new[] + { + Assembly.GetAssembly(typeof(RequiredAttribute))!, + Assembly.GetAssembly(typeof(TimeSpanAttribute))!, + Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!, + Assembly.GetAssembly(typeof(IValidateOptions))!, + }, + sources) + .ConfigureAwait(false); + + Assert.Empty(d); + _ = Assert.Single(r); + +#if NETCOREAPP3_1_OR_GREATER + string baseline = File.ReadAllText(@"Baselines/NetCoreApp/Validators.g.cs"); +#else + string baseline = File.ReadAllText(@"Baselines/NetFX/Validators.g.cs"); +#endif + + string result = r[0].SourceText.ToString(); + Assert.Equal(baseline, result); + // string golden = File.ReadAllText(@"generated/Microsoft.Extensions.Options.SourceGeneration/Microsoft.Extensions.Options.Generators.Generator/Validators.g.cs"); + // Assert.Equal(golden, result); +#pragma warning restore RS1035 + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadOnlyList.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadOnlyList.cs new file mode 100644 index 0000000000000..cf0d931284d4b --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadOnlyList.cs @@ -0,0 +1,58 @@ +// 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; + +#pragma warning disable CA1716 +namespace Microsoft.Shared.Collections; +#pragma warning restore CA1716 + +#if !SHARED_PROJECT +[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] +#endif + +[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Static field, lifetime matches the process")] +internal sealed class EmptyReadOnlyList : IReadOnlyList, ICollection +{ + public static readonly EmptyReadOnlyList Instance = new(); + private readonly Enumerator _enumerator = new(); + + public IEnumerator GetEnumerator() => _enumerator; + IEnumerator IEnumerable.GetEnumerator() => _enumerator; + public int Count => 0; + public T this[int index] => throw new ArgumentOutOfRangeException(nameof(index)); + + void ICollection.CopyTo(T[] array, int arrayIndex) + { + // nop + } + + bool ICollection.Contains(T item) => false; + bool ICollection.IsReadOnly => true; + void ICollection.Add(T item) => throw new NotSupportedException(); + bool ICollection.Remove(T item) => false; + + void ICollection.Clear() + { + // nop + } + + internal sealed class Enumerator : IEnumerator + { + public void Dispose() + { + // nop + } + + public void Reset() + { + // nop + } + + public bool MoveNext() => false; + public T Current => throw new InvalidOperationException(); + object IEnumerator.Current => throw new InvalidOperationException(); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadonlyDictionary.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadonlyDictionary.cs new file mode 100644 index 0000000000000..99ef907611280 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/EmptyReadonlyDictionary.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.Collections; +using System.Collections.Generic; + +#pragma warning disable CA1716 +namespace Microsoft.Shared.Collections; +#pragma warning restore CA1716 + +#if !SHARED_PROJECT +[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] +#endif + +internal sealed class EmptyReadOnlyDictionary : IReadOnlyDictionary, IDictionary + where TKey : notnull +{ + public static readonly EmptyReadOnlyDictionary Instance = new(); + + public int Count => 0; + public TValue this[TKey key] => throw new KeyNotFoundException(); + public bool ContainsKey(TKey key) => false; + public IEnumerable Keys => EmptyReadOnlyList.Instance; + public IEnumerable Values => EmptyReadOnlyList.Instance; + + public IEnumerator> GetEnumerator() => EmptyReadOnlyList>.Instance.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + ICollection IDictionary.Keys => Array.Empty(); + ICollection IDictionary.Values => Array.Empty(); + bool ICollection>.IsReadOnly => true; + TValue IDictionary.this[TKey key] + { + get => throw new KeyNotFoundException(); + set => throw new NotSupportedException(); + } + + public bool TryGetValue(TKey key, out TValue value) + { +#pragma warning disable CS8601 // The recommended implementation: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.trygetvalue + value = default; +#pragma warning restore + + return false; + } + + void ICollection>.Clear() + { + // nop + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + // nop + } + + void IDictionary.Add(TKey key, TValue value) => throw new NotSupportedException(); + bool IDictionary.Remove(TKey key) => false; + void ICollection>.Add(KeyValuePair item) => throw new NotSupportedException(); + bool ICollection>.Contains(KeyValuePair item) => false; + bool ICollection>.Remove(KeyValuePair item) => false; +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/TimeSpanAttribute.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/TimeSpanAttribute.cs new file mode 100644 index 0000000000000..e1e7639fc6af0 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/TimeSpanAttribute.cs @@ -0,0 +1,160 @@ +// 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.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +// using Microsoft.Shared.Diagnostics; + +#pragma warning disable CA1716 +namespace Microsoft.Shared.Data.Validation; +#pragma warning restore CA1716 + +/// +/// Provides boundary validation for . +/// +#if !SHARED_PROJECT +[ExcludeFromCodeCoverage] +#endif + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] +[SuppressMessage("Design", "CA1019:Define accessors for attribute arguments", Justification = "Indirectly we are.")] +internal sealed class TimeSpanAttribute : ValidationAttribute +{ + /// + /// Gets the lower bound for time span. + /// + public TimeSpan Minimum => _minMs.HasValue ? TimeSpan.FromMilliseconds((double)_minMs) : TimeSpan.Parse(_min!, CultureInfo.InvariantCulture); + + /// + /// Gets the upper bound for time span. + /// + public TimeSpan? Maximum + { + get + { + if (_maxMs.HasValue) + { + return TimeSpan.FromMilliseconds((double)_maxMs); + } + else + { + return _max == null ? null : TimeSpan.Parse(_max, CultureInfo.InvariantCulture); + } + } + } + + /// + /// Gets or sets a value indicating whether the time span validation should exclude the minimum and maximum values. + /// + /// + /// By default the property is set to false. + /// + public bool Exclusive { get; set; } + + private readonly int? _minMs; + private readonly int? _maxMs; + private readonly string? _min; + private readonly string? _max; + + /// + /// Initializes a new instance of the class. + /// + /// Minimum in milliseconds. + public TimeSpanAttribute(int minMs) + { + _minMs = minMs; + _maxMs = null; + } + + /// + /// Initializes a new instance of the class. + /// + /// Minimum in milliseconds. + /// Maximum in milliseconds. + public TimeSpanAttribute(int minMs, int maxMs) + { + _minMs = minMs; + _maxMs = maxMs; + } + + /// + /// Initializes a new instance of the class. + /// + /// Minimum represented as time span string. + public TimeSpanAttribute(string min) + { + _ = ThrowHelper.IfNullOrWhitespace(min); + + _min = min; + _max = null; + } + + /// + /// Initializes a new instance of the class. + /// + /// Minimum represented as time span string. + /// Maximum represented as time span string. + public TimeSpanAttribute(string min, string max) + { + _ = ThrowHelper.IfNullOrWhitespace(min); + _ = ThrowHelper.IfNullOrWhitespace(max); + + _min = min; + _max = max; + } + + /// + /// Validates that a given value represents an in-range TimeSpan value. + /// + /// The value to validate. + /// Additional context for this validation. + /// A value indicating success or failure. + protected override ValidationResult IsValid(object? value, ValidationContext? validationContext) + { + var min = Minimum; + var max = Maximum; + + if (min >= max) + { + throw new InvalidOperationException($"{nameof(TimeSpanAttribute)} requires that the minimum value be less than the maximum value (see field {validationContext.GetDisplayName()})"); + } + + if (value == null) + { + // use the [Required] attribute to force presence + return ValidationResult.Success!; + } + + if (value is TimeSpan ts) + { + if (Exclusive && ts <= min) + { + return new ValidationResult($"The field {validationContext.GetDisplayName()} must be > to {min}.", validationContext.GetMemberName()); + } + + if (ts < min) + { + return new ValidationResult($"The field {validationContext.GetDisplayName()} must be >= to {min}.", validationContext.GetMemberName()); + } + + if (max.HasValue) + { + if (Exclusive && ts >= max.Value) + { + return new ValidationResult($"The field {validationContext.GetDisplayName()} must be < to {max}.", validationContext.GetMemberName()); + } + + if (ts > max.Value) + { + return new ValidationResult($"The field {validationContext.GetDisplayName()} must be <= to {max}.", validationContext.GetMemberName()); + } + } + + return ValidationResult.Success!; + } + + throw new InvalidOperationException($"{nameof(TimeSpanAttribute)} can only be used with fields of type TimeSpan (see field {validationContext.GetDisplayName()})"); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/ValidationContextExtensions.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/ValidationContextExtensions.cs new file mode 100644 index 0000000000000..45d3365b2005d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Extensions/ValidationContextExtensions.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; + +#pragma warning disable CA1716 +namespace Microsoft.Shared.Data.Validation; +#pragma warning restore CA1716 + +#if !SHARED_PROJECT +[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] +#endif + +internal static class ValidationContextExtensions +{ + public static string[]? GetMemberName(this ValidationContext? validationContext) + { +#pragma warning disable S1168 // Empty arrays and collections should be returned instead of null + return validationContext?.MemberName is { } memberName + ? new[] { memberName } + : null; +#pragma warning restore S1168 // Empty arrays and collections should be returned instead of null + } + + public static string GetDisplayName(this ValidationContext? validationContext) + { + return validationContext?.DisplayName ?? string.Empty; + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/CustomAttrTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/CustomAttrTests.cs new file mode 100644 index 0000000000000..9770924b5b12d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/CustomAttrTests.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using CustomAttr; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class CustomAttrTests +{ + [Fact] + public void Invalid() + { + var firstModel = new FirstModel + { + P1 = 'a', + P2 = 'x', + }; + + var validator = new FirstValidator(); + var vr = validator.Validate("CustomAttr", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 2, "P1", "P2"); + } + + [Fact] + public void Valid() + { + var firstModel = new FirstModel + { + P1 = 'A', + P2 = 'A', + }; + + var validator = new FirstValidator(); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("CustomAttr", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/EnumerationTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/EnumerationTests.cs new file mode 100644 index 0000000000000..d2f9bddca2843 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/EnumerationTests.cs @@ -0,0 +1,93 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Enumeration; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class EnumerationTests +{ + [Fact] + public void Invalid() + { + var secondModelC = new SecondModel + { + P6 = "1234", + }; + + var secondModelB = new SecondModel + { + P6 = "12345", + }; + + var secondModel = new SecondModel + { + P6 = "1234", + }; + + ThirdModel? thirdModel = new ThirdModel + { + Value = 11 + }; + + var firstModel = new FirstModel + { + P1 = new[] { secondModel }, + P2 = new[] { secondModel, secondModelB, secondModelC }, + P51 = new[] { thirdModel } + }; + + var validator = default(FirstValidator); + var vr = validator.Validate("Enumeration", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 4, "P1[0].P6", "P2[0].P6", "P2[2].P6", "P51[0].Value"); + } + + [Fact] + public void NullElement() + { + var firstModel = new FirstModel + { + P1 = new[] { (SecondModel)null! }, + }; + + var validator = default(FirstValidator); + var vr = validator.Validate("Enumeration", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 1, "P1[0]"); + } + + [Fact] + public void Valid() + { + var secondModel = new SecondModel + { + P6 = "12345", + }; + + var thirdModelA = new ThirdModel + { + Value = 2 + }; + + var thirdModelB = new ThirdModel + { + Value = 9 + }; + + var firstModel = new FirstModel + { + P1 = new[] { secondModel }, + P2 = new[] { secondModel }, + P3 = new[] { (SecondModel?)null }, + P4 = new[] { thirdModelA, thirdModelB }, + P5 = new ThirdModel?[] { thirdModelA, default }, + P51 = new ThirdModel?[] { thirdModelB, default } + }; + + var validator = default(FirstValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Enumeration", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FieldTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FieldTests.cs new file mode 100644 index 0000000000000..3656d4f359e5f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FieldTests.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Fields; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class FieldTests +{ + [Fact] + public void Invalid() + { + var thirdModel = new ThirdModel + { + P5 = "1234", + }; + + var secondModel = new SecondModel + { + P4 = "1234", + }; + + var firstModel = new FirstModel + { + P1 = "1234", + P2 = secondModel, + P3 = thirdModel, + }; + + var validator = default(FirstValidator); + var vr = validator.Validate("Fields", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 3, "P1", "P2.P4", "P3.P5"); + } + + [Fact] + public void Valid() + { + var thirdModel = new ThirdModel + { + P5 = "12345", + P6 = 1 + }; + + var secondModel = new SecondModel + { + P4 = "12345", + }; + + var firstModel = new FirstModel + { + P1 = "12345", + P2 = secondModel, + P3 = thirdModel, + }; + + var validator = default(FirstValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Fields", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FunnyStringsTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FunnyStringsTests.cs new file mode 100644 index 0000000000000..29b62a5c4b4b9 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/FunnyStringsTests.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using FunnyStrings; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class FunnyStringsTests +{ + [Fact] + public void Invalid() + { + var firstModel = new FirstModel + { + P1 = "XXX", + }; + + var validator = default(FirstValidator); + var vr = validator.Validate("FunnyStrings", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 1, "P1"); + } + + [Fact] + public void Valid() + { + var firstModel = new FirstModel + { + P1 = "\"\r\n\\", + }; + + var validator = default(FirstValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("FunnyStrings", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/GenericsTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/GenericsTests.cs new file mode 100644 index 0000000000000..838fe5296897b --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/GenericsTests.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Generics; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class GenericsTests +{ + [Fact] + public void Invalid() + { + var secondModel = new SecondModel + { + P4 = "1234", + }; + + var firstModel = new FirstModel + { + P1 = "1234", + P3 = secondModel, + }; + + var validator = new FirstValidator(); + var vr = validator.Validate("Generics", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 2, "P1", "P3.P4"); + } + + [Fact] + public void Valid() + { + var secondModel = new SecondModel + { + P4 = "12345", + }; + + var firstModel = new FirstModel + { + P1 = "12345", + P3 = secondModel, + }; + + var validator = new FirstValidator(); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Generics", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/MultiModelValidatorTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/MultiModelValidatorTests.cs new file mode 100644 index 0000000000000..fff83ced91845 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/MultiModelValidatorTests.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options; +using MultiModelValidator; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class MultiModelValidatorTests +{ + [Fact] + public void Invalid() + { + var secondModel = new SecondModel + { + P3 = "1234", + }; + + var firstModel = new FirstModel + { + P1 = "1234", + P2 = secondModel, + }; + + var validator = default(MultiValidator); + var vr = validator.Validate("MultiModelValidator", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 2, "P1", "P2.P3"); + } + + [Fact] + public void Valid() + { + var secondModel = new SecondModel + { + P3 = "12345", + }; + + var firstModel = new FirstModel + { + P1 = "12345", + P2 = secondModel, + }; + + var validator = default(MultiValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("MultiModelValidator", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NestedTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NestedTests.cs new file mode 100644 index 0000000000000..8a4b04361a32a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NestedTests.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if ROSLYN_4_0_OR_GREATER + +using Microsoft.Extensions.Options; +using Nested; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class NestedTests +{ + [Fact] + public void Invalid() + { + var thirdModel = new Container1.ThirdModel + { + P6 = "1234", + }; + + var secondModel = new Container1.SecondModel + { + P5 = "1234", + }; + + var firstModel = new Container1.FirstModel + { + P1 = "1234", + P2 = secondModel, + P3 = thirdModel, + P4 = secondModel, + }; + + var validator = default(Container2.Container3.FirstValidator); + var vr = validator.Validate("Nested", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 4, "P1", "P2.P5", "P3.P6", "P4.P5"); + } + + [Fact] + public void Valid() + { + var thirdModel = new Container1.ThirdModel + { + P6 = "12345", + }; + + var secondModel = new Container1.SecondModel + { + P5 = "12345", + }; + + var firstModel = new Container1.FirstModel + { + P1 = "12345", + P2 = secondModel, + P3 = thirdModel, + P4 = secondModel, + }; + + var validator = default(Container2.Container3.FirstValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Nested", firstModel)); + } +} + +#endif diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NoNamespaceTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NoNamespaceTests.cs new file mode 100644 index 0000000000000..5530b63953180 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/NoNamespaceTests.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class NoNamespaceTests +{ + [Fact] + public void Invalid() + { + var thirdModel = new ThirdModelNoNamespace + { + P5 = "1234", + }; + + var secondModel = new SecondModelNoNamespace + { + P4 = "1234", + }; + + var firstModel = new FirstModelNoNamespace + { + P1 = "1234", + P2 = secondModel, + P3 = thirdModel, + }; + + var validator = new FirstValidatorNoNamespace(); + var vr = validator.Validate("NoNamespace", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 3, "P1", "P2.P4", "P3.P5"); + } + + [Fact] + public void Valid() + { + var thirdModel = new ThirdModelNoNamespace + { + P5 = "12345", + }; + + var secondModel = new SecondModelNoNamespace + { + P4 = "12345", + }; + + var firstModel = new FirstModelNoNamespace + { + P1 = "12345", + P2 = secondModel, + P3 = thirdModel, + }; + + var validator = new FirstValidatorNoNamespace(); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("NoNamespace", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs new file mode 100644 index 0000000000000..49941010f1ace --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/OptionsValidationTests.cs @@ -0,0 +1,442 @@ +// 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.ComponentModel.DataAnnotations; +using System.Globalization; +using Microsoft.Extensions.Options; +using TestClasses.OptionsValidation; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class OptionsValidationTests +{ + [Fact] + public void RequiredAttributeValid() + { + var validModel = new RequiredAttributeModel + { + Val = "val" + }; + + var modelValidator = new RequiredAttributeModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void RequiredAttributeInvalid() + { + var validModel = new RequiredAttributeModel + { + Val = null + }; + + var modelValidator = new RequiredAttributeModelValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void RegularExpressionAttributeValid() + { + var validModel = new RegularExpressionAttributeModel + { + Val = " " + }; + + var modelValidator = new RegularExpressionAttributeModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void RegularExpressionAttributeInvalid() + { + var validModel = new RegularExpressionAttributeModel + { + Val = "Not Space" + }; + + var modelValidator = new RegularExpressionAttributeModelValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void EmailAttributeValid() + { + var validModel = new EmailAttributeModel + { + Val = "abc@xyz.com" + }; + + var modelValidator = new EmailAttributeModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void EmailAttributeInvalid() + { + var validModel = new EmailAttributeModel + { + Val = "Not Email Address" + }; + + var modelValidator = new EmailAttributeModelValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void CustomValidationAttributeValid() + { + var validModel = new CustomValidationAttributeModel + { + Val = "Pass" + }; + + var modelValidator = new CustomValidationAttributeModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void CustomValidationAttributeInvalid() + { + var validModel = new CustomValidationAttributeModel + { + Val = "NOT PASS" + }; + + var modelValidator = new CustomValidationAttributeModelValidator(); + Assert.Throws(() => modelValidator.Validate(nameof(validModel), validModel)); + } + + [Fact] + public void DataTypeAttributeValid() + { + var validModel = new DataTypeAttributeModel + { + Val = "ABC" + }; + + var modelValidator = new DataTypeAttributeModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void RangeAttributeModelIntValid() + { + var validModel = new RangeAttributeModelInt + { + Val = 1 + }; + + var modelValidator = new RangeAttributeModelIntValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void RangeAttributeModelIntInvalid() + { + var validModel = new RangeAttributeModelInt + { + Val = 0 + }; + + var modelValidator = new RangeAttributeModelIntValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void RangeAttributeModelDoubleValid() + { + var validModel = new RangeAttributeModelDouble + { + Val = 0.6 + }; + + var modelValidator = new RangeAttributeModelDoubleValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void RangeAttributeModelDoubleInvalid() + { + var validModel = new RangeAttributeModelDouble + { + Val = 0.1 + }; + + var modelValidator = new RangeAttributeModelDoubleValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void RangeAttributeModelDateValid() + { +#if NETCOREAPP3_1_OR_GREATER + // Setting non-invariant culture to check that + // attribute's "ParseLimitsInInvariantCulture" property + // was set up correctly in the validator: + CultureInfo.CurrentCulture = new CultureInfo("cs"); +#else + // Setting invariant culture to avoid DateTime parsing discrepancies: + CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; +#endif + var validModel = new RangeAttributeModelDate + { + Val = new DateTime(day: 3, month: 1, year: 2004) + }; + + var modelValidator = new RangeAttributeModelDateValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void RangeAttributeModelDateInvalid() + { + var validModel = new RangeAttributeModelDate + { + Val = new DateTime(day: 1, month: 1, year: 2004) + }; + + var modelValidator = new RangeAttributeModelDateValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void MultipleAttributeModelValid() + { + var validModel = new MultipleAttributeModel + { + Val1 = "abc", + Val2 = 2, + Val3 = 4, + Val4 = 6 + }; + + var modelValidator = new MultipleAttributeModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Theory] + [InlineData("", 2, 4, 7)] + [InlineData(null, 2, 4, 7)] + [InlineData("abc", 0, 4, 9)] + [InlineData("abc", 2, 8, 8)] + [InlineData("abc", 2, 4, 10)] + public void MultipleAttributeModelInvalid(string val1, int val2, int val3, int val4) + { + var validModel = new MultipleAttributeModel + { + Val1 = val1, + Val2 = val2, + Val3 = val3, + Val4 = val4 + }; + + var modelValidator = new MultipleAttributeModelValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void CustomTypeCustomValidationAttributeModelValid() + { + var validModel = new CustomTypeCustomValidationAttributeModel + { + Val = new CustomType { Val1 = "Pass", Val2 = "Pass" } + }; + + var modelValidator = new CustomTypeCustomValidationAttributeModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void CustomTypeCustomValidationAttributeModelInvalid() + { + var validModel = new CustomTypeCustomValidationAttributeModel + { + Val = new CustomType { Val1 = "Pass", Val2 = "Not Pass" } + }; + + var modelValidator = new CustomTypeCustomValidationAttributeModelValidator(); + Assert.Throws(() => modelValidator.Validate(nameof(validModel), validModel)); + } + + [Fact] + public void DerivedModelIsValid() + { + var validModel = new DerivedModel + { + Val = 1, + DerivedVal = "Valid", + VirtualValWithAttr = 1, + VirtualValWithoutAttr = null + }; + + ((RequiredAttributeModel)validModel).Val = "Valid hidden member from base class"; + + var validator = new DerivedModelValidator(); + var result = validator.Validate(nameof(validModel), validModel); + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Theory] + [InlineData(0, "", 1, null, "Valid hidden member from base class")] + [InlineData(null, "Valid", 1, null, "Valid hidden member from base class")] + [InlineData(1, "Valid", null, null, "Valid hidden member from base class")] + public void DerivedModelIsInvalid(int? val, string? derivedVal, int? virtValAttr, int? virtVal, string? hiddenValBaseClass) + { + var invalidModel = new DerivedModel + { + Val = val, + DerivedVal = derivedVal, + VirtualValWithAttr = virtValAttr, + VirtualValWithoutAttr = virtVal + }; + + ((RequiredAttributeModel)invalidModel).Val = hiddenValBaseClass; + + var validator = new DerivedModelValidator(); + Utils.VerifyValidateOptionsResult(validator.Validate(nameof(invalidModel), invalidModel), 1); + } + + [Fact] + public void LeafModelIsValid() + { + var validModel = new LeafModel + { + Val = 1, + DerivedVal = "Valid", + VirtualValWithAttr = null, + VirtualValWithoutAttr = 1 + }; + + ((RequiredAttributeModel)validModel).Val = "Valid hidden member from base class"; + + var validator = new LeafModelValidator(); + var result = validator.Validate(nameof(validModel), validModel); + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void ComplexModelValid() + { + var validModel = new ComplexModel + { + ComplexVal = new RequiredAttributeModel { Val = "Valid" } + }; + + var modelValidator = new ComplexModelValidator(); + var result = modelValidator.Validate(nameof(validModel), validModel); + Assert.Equal(ValidateOptionsResult.Success, result); + + validModel = new ComplexModel + { + ValWithoutOptionsValidator = new TypeWithoutOptionsValidator + { + Val1 = "Valid", + Val2 = new DateTime(day: 3, month: 1, year: 2004) + } + }; + + // Setting invariant culture to avoid DateTime parsing discrepancies: + CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; + result = modelValidator.Validate(nameof(validModel), validModel); + Assert.Equal(ValidateOptionsResult.Success, result); + + validModel = new ComplexModel + { + ValWithoutOptionsValidator = new TypeWithoutOptionsValidator + { + Val1 = "A", + Val2 = new DateTime(day: 2, month: 2, year: 2004), + YetAnotherComplexVal = new RangeAttributeModelDouble { Val = 0.7 } + } + }; + + result = modelValidator.Validate(nameof(validModel), validModel); + Assert.Equal(ValidateOptionsResult.Success, result); + } + + [Fact] + public void ComplexModelInvalid() + { + var invalidModel = new ComplexModel + { + ComplexVal = new RequiredAttributeModel { Val = null } + }; + + var modelValidator = new ComplexModelValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1); + + invalidModel = new ComplexModel + { + ValWithoutOptionsValidator = new TypeWithoutOptionsValidator { Val1 = "Valid", Val2 = new DateTime(2003, 3, 3) } + }; + + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1); + + invalidModel = new ComplexModel + { + ValWithoutOptionsValidator = new TypeWithoutOptionsValidator { Val1 = string.Empty, Val2 = new DateTime(2004, 3, 3) } + }; + + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1); + + invalidModel = new ComplexModel + { + ValWithoutOptionsValidator = new TypeWithoutOptionsValidator + { + Val1 = "A", + Val2 = new DateTime(2004, 2, 2), + YetAnotherComplexVal = new RangeAttributeModelDouble { Val = 0.4999 } + } + }; + + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1); + } + + [Fact] + public void AttributePropertyModelTestOnErrorMessage() + { + var validModel = new AttributePropertyModel + { + Val1 = 5, + Val2 = 1 + }; + + var modelValidator = new AttributePropertyModelValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } + + [Fact] + public void AttributePropertyModelTestOnErrorMessageResource() + { + var validModel = new AttributePropertyModel + { + Val1 = 1, + Val2 = 5 + }; + + var modelValidator = new AttributePropertyModelValidator(); + Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RandomMembersTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RandomMembersTests.cs new file mode 100644 index 0000000000000..1c87892b27952 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RandomMembersTests.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options; +using RandomMembers; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class RandomMembersTests +{ + [Fact] + public void Invalid() + { + var firstModel = new FirstModel + { + P1 = "1234", + }; + + var validator = new FirstValidator(); + var vr = validator.Validate("RandomMembers", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 1, "P1"); + } + + [Fact] + public void Valid() + { + var firstModel = new FirstModel + { + P1 = "12345", + }; + + var validator = new FirstValidator(); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("RandomMembers", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RecordTypesTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RecordTypesTests.cs new file mode 100644 index 0000000000000..bd0d872c8b686 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RecordTypesTests.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if ROSLYN_4_0_OR_GREATER + +using Microsoft.Extensions.Options; +using RecordTypes; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class RecordTypesTests +{ + [Fact] + public void Invalid() + { + var thirdModel = new ThirdModel + { + P6 = "1234", + }; + + var secondModel = new SecondModel + { + P5 = "1234", + }; + + var firstModel = new FirstModel + { + P1 = "1234", + P2 = secondModel, + P3 = secondModel, + P4 = thirdModel, + }; + + var validator = default(FirstValidator); + var vr = validator.Validate("RecordTypes", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 4, "P1", "P2.P5", "P3.P5", "P4.P6"); + } + + [Fact] + public void Valid() + { + var thirdModel = new ThirdModel + { + P6 = "12345", + }; + + var secondModel = new SecondModel + { + P5 = "12345", + }; + + var firstModel = new FirstModel + { + P1 = "12345", + P2 = secondModel, + P3 = secondModel, + P4 = thirdModel, + }; + + var validator = default(FirstValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("RecordTypes", firstModel)); + } +} + +#endif diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RepeatedTypesTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RepeatedTypesTests.cs new file mode 100644 index 0000000000000..b45fcbf9ced02 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/RepeatedTypesTests.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options; +using RepeatedTypes; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class RepeatedTypesTests +{ + [Fact] + public void Invalid() + { + var thirdModel = new ThirdModel + { + P5 = "1234", + }; + + var secondModel = new SecondModel + { + P4 = thirdModel, + }; + + var firstModel = new FirstModel + { + P1 = secondModel, + P2 = secondModel, + P3 = thirdModel, + }; + + var validator = new FirstValidator(); + var vr = validator.Validate("RepeatedTypes", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 3, "P1.P4.P5", "P2.P4.P5", "P3.P5"); + } + + [Fact] + public void Valid() + { + var thirdModel = new ThirdModel + { + P5 = "12345", + }; + + var secondModel = new SecondModel + { + P4 = thirdModel, + }; + + var firstModel = new FirstModel + { + P1 = secondModel, + P2 = secondModel, + P3 = thirdModel, + }; + + var validator = new FirstValidator(); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("RepeatedTypes", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/SelfValidationTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/SelfValidationTests.cs new file mode 100644 index 0000000000000..0a511333f0357 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/SelfValidationTests.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options; +using SelfValidation; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class SelfValidationTests +{ + [Fact] + public void Invalid() + { + var firstModel = new FirstModel + { + P1 = "1234", + }; + + var validator = default(FirstValidator); + var vr = validator.Validate("SelfValidation", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 1, "P1"); + } + + [Fact] + public void Valid() + { + var firstModel = new FirstModel + { + P1 = "12345", + }; + + var validator = default(FirstValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("SelfValidation", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs new file mode 100644 index 0000000000000..7412374f18a56 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/Utils.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NETCOREAPP3_1_OR_GREATER +using System.Linq; +#endif +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +internal static class Utils +{ + public static void VerifyValidateOptionsResult(ValidateOptionsResult vr, int expectedErrorCount, params string[] expectedErrorSubstrings) + { + Assert.NotNull(vr); + +#if NETCOREAPP3_1_OR_GREATER + var failures = vr.Failures!.ToArray(); +#else + var failures = vr.FailureMessage!.Split(';'); +#endif + + Assert.Equal(expectedErrorCount, failures.Length); + + for (int i = 0; i < expectedErrorSubstrings.Length; i++) + { + Assert.Contains(expectedErrorSubstrings[i], failures[i]); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/ValueTypesTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/ValueTypesTests.cs new file mode 100644 index 0000000000000..543e8eb882b20 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Generated/ValueTypesTests.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options; +using ValueTypes; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public class ValueTypesTests +{ + [Fact] + public void Invalid() + { + var secondModel = new SecondModel + { + P4 = "1234", + }; + + var firstModel = new FirstModel + { + P1 = "1234", + P3 = secondModel, + P2 = secondModel, + P4 = default, + }; + + var validator = default(FirstValidator); + var vr = validator.Validate("ValueTypes", firstModel); + + Utils.VerifyValidateOptionsResult(vr, 3, "P1", "P2.P4", "P3.P4"); + } + + [Fact] + public void Valid() + { + var secondModel = new SecondModel + { + P4 = "12345", + }; + + var firstModel = new FirstModel + { + P1 = "12345", + P3 = secondModel, + P2 = secondModel, + P4 = default, + }; + + var validator = default(FirstValidator); + Assert.Equal(ValidateOptionsResult.Success, validator.Validate("ValueTypes", firstModel)); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj new file mode 100644 index 0000000000000..54f7dfdade3c8 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Microsoft.Extensions.Options.SourceGeneration.Tests.csproj @@ -0,0 +1,55 @@ + + + $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(MicrosoftCodeAnalysisVersion_4_4) + true + + true + + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER;ROSLYN_4_0_OR_GREATER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + PreserveNewest + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs new file mode 100644 index 0000000000000..5663a16021c2d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs @@ -0,0 +1,214 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options.Generators; +using SourceGenerators.Tests; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public partial class ParserTests +{ + [Fact] + public async Task CircularTypeReferencesInEnumeration() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateEnumeratedItems] + public FirstModel[]? P1 { get; set; } + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, d[0].Id); + } + + [Fact] + public async Task NotValidatorInEnumeration() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateEnumeratedItems(typeof(SecondValidator)] + public SecondModel[]? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + public partial class SecondValidator + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); + } + + [Fact] + public async Task NullValidatorInEnumeration() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateEnumeratedItems(null!)] + public SecondModel[]? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.NullValidatorType.Id, d[0].Id); + } + + [Fact] + public async Task NoSimpleValidatorConstructorInEnumeration() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + + [ValidateEnumeratedItems(typeof(SecondValidator)] + public SecondModel[]? P2; + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + public SecondValidator(int _) + { + } + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, d[0].Id); + } + + [Fact] + public async Task CantValidateOpenGenericMembersInEnumeration() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateEnumeratedItems] + public T[]? P1; + + [ValidateEnumeratedItems] + [Required] + public T[]? P2; + + [ValidateEnumeratedItems] + [Required] + public System.Collections.Generic.IList P3 = null!; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(3, d.Count); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[0].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[1].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[2].Id); + } + + [Fact] + public async Task ClosedGenericsInEnumeration() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateEnumeratedItems] + [Required] + public T[]? P1; + + [ValidateEnumeratedItems] + [Required] + public int[]? P2; + + [ValidateEnumeratedItems] + [Required] + public System.Collections.Generic.IList? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(3, d.Count); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[1].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[2].Id); + } + + [Fact] + public async Task NotEnumerable() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateEnumeratedItems] + public int P1; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + Assert.Equal(1, d.Count); + Assert.Equal(DiagDescriptors.NotEnumerableType.Id, d[0].Id); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs new file mode 100644 index 0000000000000..55e541f48fc3d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs @@ -0,0 +1,930 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using SourceGenerators.Tests; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.ComponentModel.DataAnnotations; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options.Generators; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Test; + +public partial class ParserTests +{ + [Fact] + public async Task PotentiallyMissingAttributes() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public SecondModel? P1 { get; set; } + + [Required] + public System.Collections.Generic.IList? P2 { get; set; } + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + Assert.Equal(2, d.Count); + Assert.Equal(DiagDescriptors.PotentiallyMissingTransitiveValidation.Id, d[0].Id); + Assert.Equal(DiagDescriptors.PotentiallyMissingEnumerableValidation.Id, d[1].Id); + } + + [Fact] + public async Task CircularTypeReferences() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public FirstModel? P1 { get; set; } + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, d[0].Id); + } + + [Fact] + public async Task InvalidValidatorInterface() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); + } + + [Fact] + public async Task NotValidator() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateObjectMembers(typeof(SecondValidator)] + public SecondModel? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + public partial class SecondValidator + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); + } + + [Fact] + public async Task ValidatorAlreadyImplementValidateFunction() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + + [ValidateObjectMembers(typeof(SecondValidator)] + public SecondModel? P2; + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + public ValidateOptionsResult Validate(string name, SecondModel options) + { + throw new System.NotSupportedException(); + } + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, d[0].Id); + } + + [Fact] + public async Task NullValidator() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateObjectMembers(null!)] + public SecondModel? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.NullValidatorType.Id, d[0].Id); + } + + [Fact] + public async Task NoSimpleValidatorConstructor() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + + [ValidateObjectMembers(typeof(SecondValidator)] + public SecondModel? P2; + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + public SecondValidator(int _) + { + } + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, d[0].Id); + } + + [Fact] + public async Task NoStaticValidator() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string P1; + } + + [OptionsValidator] + public static partial class FirstValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.CantBeStaticClass.Id, d[0].Id); + } + + [Fact] + public async Task BogusModelType() + { + var (d, _) = await RunGenerator(@" + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + // the generator doesn't produce any errors here, since the C# compiler will take care of it + Assert.Empty(d); + } + + [Fact] + public async Task CantValidateOpenGenericMembers() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public T? P1; + + [ValidateObjectMembers] + [Required] + public T[]? P2; + + [ValidateObjectMembers] + [Required] + public System.Collections.Generics.IList P3 = null!; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(3, d.Count); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[0].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[1].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[2].Id); + } + + [Fact] + public async Task ClosedGenerics() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public T? P1; + + [ValidateObjectMembers] + [Required] + public T[]? P2; + + [ValidateObjectMembers] + [Required] + public int[]? P3; + + [ValidateObjectMembers] + [Required] + public System.Collections.Generics.IList? P4; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(4, d.Count); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[1].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[2].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[3].Id); + } + + [Fact] + public async Task NoEligibleMembers() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public SecondModel? P1; + } + + public class SecondModel + { + public string P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + } + "); + + Assert.Equal(2, d.Count); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); + Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, d[1].Id); + } + + [Fact] + public async Task AlreadyImplemented() + { + var (d, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string One { get; set; } = string.Empty; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + public void Validate(string name, FirstModel fm) + { + } + } + "); + + _ = Assert.Single(d); + Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, d[0].Id); + } + + [Fact] + public async Task ShouldNotProduceInfoWhenTheClassHasABaseClass() + { + var (d, _) = await RunGenerator(@" + public class Parent + { + [Required] + public string parentString { get; set; } + } + + public class Child : Parent + { + [Required] + public string childString { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldNotProduceInfoWhenTransitiveClassHasABaseClass() + { + var (d, _) = await RunGenerator(@" + public class Parent + { + [Required] + public string parentString { get; set; } + } + + public class Child : Parent + { + [Required] + public string childString { get; set; } + } + + public class MyOptions + { + [ValidateObjectMembers] + public Child childVal { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Theory] + [InlineData("bool")] + [InlineData("int")] + [InlineData("double")] + [InlineData("string")] + [InlineData("System.String")] + [InlineData("System.DateTime")] + public async Task ShouldProduceWarn_WhenTransitiveAttrMisused(string memberClass) + { + var (d, _) = await RunGenerator(@$" + public class InnerModel + {{ + [Required] + public string childString {{ get; set; }} + }} + + public class MyOptions + {{ + [Required] + public string simpleVal {{ get; set; }} + + [ValidateObjectMembers] + public {memberClass} complexVal {{ get; set; }} + }} + + [OptionsValidator] + public partial class Validator : IValidateOptions + {{ + }} + "); + + Assert.Single(d); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); + } + + [Fact] + public async Task ShouldProduceWarningWhenTheClassHasNoEligibleMembers() + { + var (d, _) = await RunGenerator(@" + public class Child + { + private string AccountName { get; set; } + public object Weight; + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Single(d); + Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, d[0].Id); + } + + [Theory] + [InlineData("private")] + [InlineData("protected")] + public async Task ShouldProduceWarningWhenTheClassMembersAreInaccessible(string accessModifier) + { + var (d, _) = await RunGenerator($@" + public class Model + {{ + [Required] + public string? PublicVal {{ get; set; }} + + [Required] + {accessModifier} string? Val {{ get; set; }} + }} + + [OptionsValidator] + public partial class Validator : IValidateOptions + {{ + }} + "); + + Assert.Single(d); + Assert.Equal("SYSLIB1206", d[0].Id); + } + + [Fact] + public async Task ShouldNotProduceErrorWhenMultipleValidationAnnotationsExist() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [MinLength(5)] + [MaxLength(15)] + public string Val9 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldNotProduceErrorWhenDataTypeAttributesAreUsed() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [CreditCard] + public string Val3 = """"; + + [EmailAddress] + public string Val6 { get; set; } + + [EnumDataType(typeof(string))] + public string Val7 { get; set; } + + [FileExtensions] + public string Val8 { get; set; } + + [Phone] + public string Val10 { get; set; } + + [Url] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldNotProduceErrorWhenConstVariableIsUsedAsAttributeArgument() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + private const int q = 5; + [Range(q, 10)] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + // Testing on all existing & eligible annotations extending ValidationAttribute that aren't used above + [Fact] + public async Task ShouldNotProduceAnyMessagesWhenExistingValidationsArePlaced() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [Required] + public string Val { get; set; } + + [Compare(""val"")] + public string Val2 { get; set; } + + [DataType(DataType.Password)] + public string _val5 = """"; + + [Range(5.1, 10.11)] + public string Val12 { get; set; } + + [Range(typeof(MemberDeclarationSyntax), ""1/2/2004"", ""3/4/2004"")] + public string Val14 { get; set; } + + [RegularExpression("""")] + public string Val15 { get; set; } + + [StringLength(5)] + public string Val16 { get; set; } + + [CustomValidation(typeof(MemberDeclarationSyntax), ""CustomMethod"")] + public string Val17 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldNotProduceErrorWhenPropertiesAreUsedAsAttributeArgument() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + private const int q = 5; + [Range(q, 10, ErrorMessage = ""ErrorMessage"")] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldSkipWhenOptionsValidatorAttributeDoesNotExist() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + private const int q = 5; + [Range(q, 10, ErrorMessage = ""ErrorMessage"")] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + ", includeOptionValidatorReferences: false); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldSkipAtrributeWhenAttributeSymbolCannotBeFound() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [RandomTest] + public string Val11 { get; set; } + + [Range(1, 10, ErrorMessage = ""ErrorMessage"")] + public string Val12 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldSkipAtrributeWhenAttributeSymbolIsNotBasedOnValidationAttribute() + { + var (d, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [FilterUIHint(""MultiForeignKey"")] + public string Val11 { get; set; } + + [Range(1, 10, ErrorMessage = ""ErrorMessage"")] + public string Val12 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldAcceptAtrributeWhenAttributeIsInDifferentNamespace() + { + var (d, _) = await RunGenerator(@" + namespace Test { + public class IValidateOptionsTestFile + { + [Test] + public string Val11 { get; set; } + } + + [AttributeUsage(AttributeTargets.Class)] + public sealed class TestAttribute : ValidationAttribute + { + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + } + ", inNamespace: false); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldHandleAtrributePropertiesOtherThanString() + { + var (d, _) = await RunGenerator(@" + namespace Test { + public class IValidateOptionsTestFile + { + [Test(num = 5)] + public string Val11 { get; set; } + + [Required] + public string Val12 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + } + + namespace System.ComponentModel.DataAnnotations { + [AttributeUsage(AttributeTargets.Class)] + public sealed class TestAttribute : ValidationAttribute + { + public int num { get; set; } + public TestAttribute() { + } + } + } + ", inNamespace: false); + + Assert.Empty(d); + } + + [Fact] + public async Task ShouldStoreFloatValuesCorrectly() + { + var backupCulture = CultureInfo.CurrentCulture; + CultureInfo.CurrentCulture = new CultureInfo("ru-RU", false); + try + { + var (diagMessages, generatedResults) = await RunGenerator(@" + public class Model + { + [Range(-0.1, 1.3)] + public string Val { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagMessages); + Assert.Single(generatedResults); + Assert.DoesNotContain("0,1", generatedResults[0].SourceText.ToString()); + Assert.DoesNotContain("1,3", generatedResults[0].SourceText.ToString()); + } + finally + { + CultureInfo.CurrentCulture = backupCulture; + } + } + + [Fact] + public async Task MultiModelValidatorGeneratesOnlyOnePartialTypeBlock() + { + var (d, sources) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string P1 { get; set; } + } + + public class SecondModel + { + [Required] + public string P2 { get; set; } + } + + public class ThirdModel + { + [Required] + public string P3 { get; set; } + } + + [OptionsValidator] + public partial class MultiValidator : IValidateOptions, IValidateOptions, IValidateOptions + { + } + "); + + var typeDeclarations = sources[0].SyntaxTree + .GetRoot() + .DescendantNodes() + .OfType() + .ToArray(); + + var multiValidatorTypeDeclarations = typeDeclarations + .Where(x => x.Identifier.ValueText == "MultiValidator") + .ToArray(); + + Assert.Single(multiValidatorTypeDeclarations); + + var validateMethodDeclarations = multiValidatorTypeDeclarations[0] + .DescendantNodes() + .OfType() + .Where(x => x.Identifier.ValueText == "Validate") + .ToArray(); + + Assert.Equal(3, validateMethodDeclarations.Length); + } + + private static async Task<(IReadOnlyList diagnostics, ImmutableArray generatedSources)> RunGenerator( + string code, + bool wrap = true, + bool inNamespace = true, + bool includeOptionValidatorReferences = true, + bool includeSystemReferences = true, + bool includeOptionsReferences = true, + bool includeTransitiveReferences = true) + { + var text = code; + if (wrap) + { + var nspaceStart = "namespace Test {"; + var nspaceEnd = "}"; + if (!inNamespace) + { + nspaceStart = ""; + nspaceEnd = ""; + } + + text = $@" + {nspaceStart} + using System.ComponentModel.DataAnnotations; + using Microsoft.Extensions.Options.Validation; + using Microsoft.Shared.Data.Validation; + using Microsoft.Extensions.Options; + using Microsoft.CodeAnalysis.CSharp.Syntax; + {code} + {nspaceEnd} + "; + } + + var assemblies = new List { Assembly.GetAssembly(typeof(MemberDeclarationSyntax))! }; + + if (includeOptionValidatorReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!); + } + + if (includeSystemReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(RequiredAttribute))!); + } + + if (includeOptionsReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(IValidateOptions))!); + } + + if (includeTransitiveReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(Microsoft.Extensions.Options.ValidateObjectMembersAttribute))!); + } + + var result = await RoslynTestUtils.RunGenerator(new Generator(), assemblies.ToArray(), new[] { text }) + .ConfigureAwait(false); + + return result; + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx new file mode 100644 index 0000000000000..5de24c6e4868f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ErrorMessageResourceName + + + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + + + Member potentially missing enumerable validation + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + + + There is a circular type reference involving type {0} preventing it from being used for static validation + + + Unsupported circular references in model types + + + Can't apply validation attributes to private field or property {0} + + + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + + + A member type has no fields or properties to validate + + + A type has no fields or properties to validate + + + Member type is not enumerable + + + Validator type {0} doesn't have a parameterless constructor + + + Type {0} does not implement the required IValidateOptions<{1}> interface + + + Validators used for transitive or enumerable validation must have a constructor with no parameters + + + Type {0} has no fields or properties to validate, referenced by type {1} + + + Type {0} has no fields or properties to validate, referenced from member {1} + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + Can't validate private fields or properties + + + [OptionsValidator] cannot be applied to static class {0} + + + A type already includes an implementation of the `Validate` method + + + Type {0} already implements the Validate method + + + `OptionsValidatorAttribute` can't be applied to a static class + + + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + Member potentially missing transitive validation + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/CustomAttr.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/CustomAttr.cs new file mode 100644 index 0000000000000..aa75c2e5ee8ef --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/CustomAttr.cs @@ -0,0 +1,68 @@ +// 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.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace CustomAttr +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 +#pragma warning disable CA1019 +#pragma warning disable IDE0052 + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] + public sealed class CustomAttribute : ValidationAttribute + { + private readonly char _ch; + private readonly bool _caseSensitive; + private readonly string? _extra; + + public CustomAttribute(char ch, bool caseSensitive, string? extra) + { + _ch = ch; + _caseSensitive = caseSensitive; + _extra = extra; + } + + protected override ValidationResult IsValid(object? value, ValidationContext? validationContext) + { + if (value == null) + { + return ValidationResult.Success!; + } + + if (_caseSensitive) + { + if ((char)value != _ch) + { + return new ValidationResult($"{validationContext?.MemberName} didn't match"); + } + } + else + { + if (char.ToUpperInvariant((char)value) != char.ToUpperInvariant(_ch)) + { + return new ValidationResult($"{validationContext?.MemberName} didn't match"); + } + } + + return ValidationResult.Success!; + } + } + + public class FirstModel + { + [Custom('A', true, null)] + public char P1 { get; set; } + + [Custom('A', false, "X")] + public char P2 { get; set; } + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Enumeration.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Enumeration.cs new file mode 100644 index 0000000000000..549e5fbb82e8f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Enumeration.cs @@ -0,0 +1,93 @@ +// 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 System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Extensions.Options; + +namespace Enumeration +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 + + public class FirstModel + { + [ValidateEnumeratedItems] + public IList? P1; + + [ValidateEnumeratedItems(typeof(SecondValidator))] + public IList? P2; + + [ValidateEnumeratedItems] + public IList? P3; + + [ValidateEnumeratedItems] + public IList? P4; + + [ValidateEnumeratedItems] + public IList? P5; + + [ValidateEnumeratedItems] + [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1125:Use shorthand for nullable types", Justification = "Testing System>Nullable")] + public IList>? P51; + + [ValidateEnumeratedItems] + public SynteticEnumerable? P6; + + [ValidateEnumeratedItems] + public SynteticEnumerable P7; + + [ValidateEnumeratedItems] + [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1125:Use shorthand for nullable types", Justification = "Testing System>Nullable")] + public Nullable P8; + } + + public class SecondModel + { + [Required] + [MinLength(5)] + public string P6 = string.Empty; + } + + public struct ThirdModel + { + [Range(0, 10)] + public int Value; + } + + public struct SynteticEnumerable : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public IEnumerator GetEnumerator() => new InternalEnumerator(); + + private class InternalEnumerator : IEnumerator + { + public SecondModel Current => throw new NotSupportedException(); + + object IEnumerator.Current => Current; + + public void Dispose() + { + // Nothing to dispose... + } + + public bool MoveNext() => false; + + public void Reset() => throw new NotSupportedException(); + } + } + + [OptionsValidator] + public partial struct FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial struct SecondValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Fields.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Fields.cs new file mode 100644 index 0000000000000..0a6ab1470e321 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Fields.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace Fields +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 +#pragma warning disable S1186 +#pragma warning disable CA1822 + + public class FirstModel + { + [Required] + [MinLength(5)] + public string P1 = string.Empty; + + [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(SecondValidator))] + public SecondModel? P2; + + [Microsoft.Extensions.Options.ValidateObjectMembers] + public ThirdModel P3; + } + + public class SecondModel + { + [Required] + [MinLength(5)] + public string P4 = string.Empty; + } + + public struct ThirdModel + { + [Required] + [MinLength(5)] + public string P5 = string.Empty; + + public int P6 = default; + + public ThirdModel(object _) + { + } + } + + [OptionsValidator] + public partial struct FirstValidator : IValidateOptions + { + public void Validate() + { + } + + public void Validate(int _) + { + } + + public void Validate(string? _) + { + } + + public void Validate(string? _0, object _1) + { + } + } + + [OptionsValidator] + public partial struct SecondValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FileScopedNamespace.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FileScopedNamespace.cs new file mode 100644 index 0000000000000..cf76ea3497f1e --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FileScopedNamespace.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace FileScopedNamespace; + +#pragma warning disable SA1649 // File name should match first type name + +public class FirstModel +{ + [Required] + [MinLength(5)] + public string P1 = string.Empty; +} + +[OptionsValidator] +public partial struct FirstValidator : IValidateOptions +{ +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FunnyStrings.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FunnyStrings.cs new file mode 100644 index 0000000000000..c1c874ab301f0 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/FunnyStrings.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace FunnyStrings +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 + + public class FirstModel + { + [RegularExpression("\"\r\n\\\\")] + public string P1 { get; set; } = string.Empty; + } + + [OptionsValidator] + public partial struct FirstValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Generics.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Generics.cs new file mode 100644 index 0000000000000..51a59a73972e9 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Generics.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace Generics +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 + + public class FirstModel + { + [Required] + [MinLength(5)] + public string P1 { get; set; } = string.Empty; + + public T? P2 { get; set; } + + [Microsoft.Extensions.Options.ValidateObjectMembers] + public SecondModel? P3 { get; set; } + } + + public class SecondModel + { + [Required] + [MinLength(5)] + public string P4 { get; set; } = string.Empty; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs new file mode 100644 index 0000000000000..31993d093759a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Models.cs @@ -0,0 +1,251 @@ +// 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.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; +using Microsoft.Gen.OptionsValidation.Test; + +#pragma warning disable SA1649 +#pragma warning disable SA1402 + +namespace TestClasses.OptionsValidation +{ + // ValidationAttribute without parameter + public class RequiredAttributeModel + { + [Required] + public string? Val { get; set; } + } + + // ValidationAttribute with string parameter + public class RegularExpressionAttributeModel + { + [RegularExpression("\\s")] + public string Val { get; set; } = string.Empty; + } + + // DataTypeAttribute + public class EmailAttributeModel + { + [EmailAddress] + public string Val { get; set; } = string.Empty; + } + + // ValidationAttribute with System.Type parameter + public class CustomValidationAttributeModel + { + [CustomValidation(typeof(CustomValidationTest), "TestMethod")] + public string Val { get; set; } = string.Empty; + } + +#pragma warning disable SA1204 // Static elements should appear before instance elements + public static class CustomValidationTest +#pragma warning restore SA1204 // Static elements should appear before instance elements + { + public static ValidationResult? TestMethod(string val, ValidationContext _) + { + if (val.Equals("Pass", StringComparison.Ordinal)) + { + return ValidationResult.Success; + } + + throw new ValidationException(); + } + } + + // ValidationAttribute with DataType parameter + public class DataTypeAttributeModel + { + [DataType(DataType.Text)] + public string Val { get; set; } = string.Empty; + } + + // ValidationAttribute with type, double, int parameters + public class RangeAttributeModelInt + { + [Range(1, 3)] + public int Val { get; set; } + } + + public class RangeAttributeModelDouble + { + [Range(0.5, 0.9)] + public double Val { get; set; } + } + + public class RangeAttributeModelDate + { +#if NETCOREAPP3_1_OR_GREATER + [Range(typeof(DateTime), "1/2/2004", "3/4/2004", ParseLimitsInInvariantCulture = true)] +#else + [Range(typeof(DateTime), "1/2/2004", "3/4/2004")] +#endif + public DateTime Val { get; set; } + } + + public class MultipleAttributeModel + { + [Required] + [DataType(DataType.Password)] + public string Val1 { get; set; } = string.Empty; + + [Range(1, 3)] + public int Val2 { get; set; } + + [Range(3, 5)] + public int Val3 { get; set; } + + [Range(5, 9)] + public int Val4 { get; set; } + } + + public class CustomTypeCustomValidationAttributeModel + { + [CustomValidation(typeof(CustomTypeCustomValidationTest), "TestMethod")] + public CustomType? Val { get; set; } + } + + public class CustomType + { + public string Val1 { get; set; } = string.Empty; + public string Val2 { get; set; } = string.Empty; + } + +#pragma warning disable SA1204 // Static elements should appear before instance elements + public static class CustomTypeCustomValidationTest +#pragma warning restore SA1204 // Static elements should appear before instance elements + { + public static ValidationResult? TestMethod(CustomType val, ValidationContext _) + { + if (val.Val1.Equals("Pass", StringComparison.Ordinal) && val.Val2.Equals("Pass", StringComparison.Ordinal)) + { + return ValidationResult.Success; + } + + throw new ValidationException(); + } + } + + public class AttributePropertyModel + { + [Range(1, 3, ErrorMessage = "ErrorMessage")] + public int Val1 { get; set; } + + [Range(1, 3, ErrorMessageResourceType = typeof(SR), ErrorMessageResourceName = "ErrorMessageResourceName")] + public int Val2 { get; set; } + } + + public class TypeWithoutOptionsValidator + { + [Required] + public string? Val1 { get; set; } + + [Range(typeof(DateTime), "1/2/2004", "3/4/2004")] + public DateTime Val2 { get; set; } + + [Microsoft.Extensions.Options.ValidateObjectMembers] + public RangeAttributeModelDouble? YetAnotherComplexVal { get; set; } + } + + public class DerivedModel : RequiredAttributeModel + { + [Required] + public string? DerivedVal { get; set; } + + [Required] + internal virtual int? VirtualValWithAttr { get; set; } + + public virtual int? VirtualValWithoutAttr { get; set; } + + [Required] + public new int? Val { get; set; } + } + + public class LeafModel : DerivedModel + { + internal override int? VirtualValWithAttr { get; set; } + + [Required] + public override int? VirtualValWithoutAttr { get; set; } + } + + public class ComplexModel + { + [Microsoft.Extensions.Options.ValidateObjectMembers] + public RequiredAttributeModel? ComplexVal { get; set; } + + [Microsoft.Extensions.Options.ValidateObjectMembers] + public TypeWithoutOptionsValidator? ValWithoutOptionsValidator { get; set; } + } + + [OptionsValidator] + public partial class RequiredAttributeModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class RegularExpressionAttributeModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class EmailAttributeModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class CustomValidationAttributeModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class DataTypeAttributeModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class RangeAttributeModelIntValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class RangeAttributeModelDoubleValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class RangeAttributeModelDateValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class MultipleAttributeModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class CustomTypeCustomValidationAttributeModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class AttributePropertyModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class DerivedModelValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class LeafModelValidator : IValidateOptions + { + } + + [OptionsValidator] + internal sealed partial class ComplexModelValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/MultiModelValidator.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/MultiModelValidator.cs new file mode 100644 index 0000000000000..2ca6c78076631 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/MultiModelValidator.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace MultiModelValidator +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 + + public class FirstModel + { + [Required] + [MinLength(5)] + public string P1 = string.Empty; + + [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(MultiValidator))] + public SecondModel? P2; + } + + public class SecondModel + { + [Required] + [MinLength(5)] + public string P3 = string.Empty; + } + + [OptionsValidator] + public partial struct MultiValidator : IValidateOptions, IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Nested.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Nested.cs new file mode 100644 index 0000000000000..262f2fe283926 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/Nested.cs @@ -0,0 +1,106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// #if ROSLYN_4_0_OR_GREATER +// #if ROSLYN4_0_OR_GREATER + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace Nested +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 + + public static class Container1 + { + public class FirstModel + { + [Required] + [MinLength(5)] + public string P1 { get; set; } = string.Empty; + + [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(Container2.Container3.SecondValidator))] + public SecondModel? P2 { get; set; } + + [Microsoft.Extensions.Options.ValidateObjectMembers] + public ThirdModel P3 { get; set; } + + [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(Container4.Container5.ThirdValidator))] + public SecondModel? P4 { get; set; } + } + + public class SecondModel + { + [Required] + [MinLength(5)] + public string P5 { get; set; } = string.Empty; + } + + public struct ThirdModel + { + public ThirdModel(int _) + { + } + + [Required] + [MinLength(5)] + public string P6 { get; set; } = string.Empty; + } + } + + public static partial class Container2 + { + public partial class Container3 + { + public Container3(int _) + { + // nothing to do + } + + [OptionsValidator] + public partial struct FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial struct SecondValidator : IValidateOptions + { + } + } + } + + public partial record class Container4 + { + public partial record class Container5 + { + public Container5(int _) + { + // nothing to do + } + + [OptionsValidator] + public partial struct ThirdValidator : IValidateOptions + { + } + } + } + + public partial struct Container6 + { + [OptionsValidator] + public partial struct FourthValidator : IValidateOptions + { + } + } + + public partial record struct Container7 + { + [OptionsValidator] + public partial record struct FifthValidator : IValidateOptions + { + } + } +} + +// #endif diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/NoNamespace.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/NoNamespace.cs new file mode 100644 index 0000000000000..1eadac9c45092 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/NoNamespace.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +#pragma warning disable SA1649 +#pragma warning disable SA1402 + +public class FirstModelNoNamespace +{ + [Required] + [MinLength(5)] + public string P1 { get; set; } = string.Empty; + + [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(SecondValidatorNoNamespace))] + public SecondModelNoNamespace? P2 { get; set; } + + [Microsoft.Extensions.Options.ValidateObjectMembers] + public ThirdModelNoNamespace? P3 { get; set; } +} + +public class SecondModelNoNamespace +{ + [Required] + [MinLength(5)] + public string P4 { get; set; } = string.Empty; +} + +public class ThirdModelNoNamespace +{ + [Required] + [MinLength(5)] + public string P5 { get; set; } = string.Empty; +} + +[OptionsValidator] +public partial class FirstValidatorNoNamespace : IValidateOptions +{ +} + +[OptionsValidator] +public partial class SecondValidatorNoNamespace : IValidateOptions +{ +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RandomMembers.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RandomMembers.cs new file mode 100644 index 0000000000000..b3c5331990a13 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RandomMembers.cs @@ -0,0 +1,34 @@ +// 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.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace RandomMembers +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 +#pragma warning disable CA1822 + + public class FirstModel + { + [Required] + [MinLength(5)] + public string? P1 { get; set; } + + public void Foo() + { + throw new NotSupportedException(); + } + + public class Nested + { + } + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RecordTypes.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RecordTypes.cs new file mode 100644 index 0000000000000..4d964ceeb4a38 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RecordTypes.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// #if ROSLYN_4_0_OR_GREATER + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace RecordTypes +{ +#pragma warning disable SA1649 + + public record class FirstModel + { + [Required] + [MinLength(5)] + public string P1 { get; set; } = string.Empty; + + [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(SecondValidator))] + public SecondModel? P2 { get; set; } + + [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(ThirdValidator))] + public SecondModel P3 { get; set; } = new SecondModel(); + + [Microsoft.Extensions.Options.ValidateObjectMembers] + public ThirdModel P4 { get; set; } + } + + public record class SecondModel + { + [Required] + [MinLength(5)] + public string P5 { get; set; } = string.Empty; + } + + public record struct ThirdModel + { + [Required] + [MinLength(5)] + public string P6 { get; set; } = string.Empty; + + public ThirdModel(int _) + { + } + + public ThirdModel(object _) + { + } + } + + [OptionsValidator] + public partial record struct FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial record struct SecondValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial record class ThirdValidator : IValidateOptions + { + } +} + +// #endif diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RepeatedTypes.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RepeatedTypes.cs new file mode 100644 index 0000000000000..db295a448aa57 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/RepeatedTypes.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace RepeatedTypes +{ +#pragma warning disable SA1649 +#pragma warning disable SA1402 +#pragma warning disable CA1019 + + public class FirstModel + { + [Required] + [Microsoft.Extensions.Options.ValidateObjectMembers] + public SecondModel? P1 { get; set; } + + [Required] + [Microsoft.Extensions.Options.ValidateObjectMembers] + public SecondModel? P2 { get; set; } + + [Required] + [Microsoft.Extensions.Options.ValidateObjectMembers] + public ThirdModel? P3 { get; set; } + } + + public class SecondModel + { + [Required] + [Microsoft.Extensions.Options.ValidateObjectMembers] + public ThirdModel? P4 { get; set; } + } + + public class ThirdModel + { + [Required] + [MinLength(5)] + public string? P5; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/SelfValidation.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/SelfValidation.cs new file mode 100644 index 0000000000000..8fe5a9aa41e8a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/SelfValidation.cs @@ -0,0 +1,33 @@ +// 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.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Options; + +namespace SelfValidation +{ +#pragma warning disable SA1649 + + public class FirstModel : IValidatableObject + { + [Required] + public string P1 = string.Empty; + + public IEnumerable Validate(ValidationContext validationContext) + { + if (P1.Length < 5) + { + return new[] { new ValidationResult("P1 is not long enough") }; + } + + return Array.Empty(); + } + } + + [OptionsValidator] + public partial struct FirstValidator : IValidateOptions + { + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/ValueTypes.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/ValueTypes.cs new file mode 100644 index 0000000000000..1cdee371d321d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/TestClasses/ValueTypes.cs @@ -0,0 +1,45 @@ +// 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.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Extensions.Options; + +namespace ValueTypes +{ +#pragma warning disable SA1649 + + public class FirstModel + { + [Required] + [MinLength(5)] + public string P1 { get; set; } = string.Empty; + + [ValidateObjectMembers] + public SecondModel? P2 { get; set; } + + [ValidateObjectMembers] + public SecondModel P3 { get; set; } + + [ValidateObjectMembers] + [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1125:Use shorthand for nullable types", Justification = "Testing System>Nullable")] + public Nullable P4 { get; set; } + } + + public struct SecondModel + { + [Required] + [MinLength(5)] + public string P4 { get; set; } = string.Empty; + + public SecondModel(object _) + { + } + } + + [OptionsValidator] + public partial struct FirstValidator : IValidateOptions + { + } +} From b662e52f4608a83119516af9194f13e90aed909c Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Wed, 14 Jun 2023 17:31:57 -0700 Subject: [PATCH 02/13] Add source gen to the package and clean up some resources --- .../gen/Resources.resx | 198 ------------------ .../src/Microsoft.Extensions.Options.csproj | 6 + 2 files changed, 6 insertions(+), 198 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.Options/gen/Resources.resx diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources.resx b/src/libraries/Microsoft.Extensions.Options/gen/Resources.resx deleted file mode 100644 index d9bae1523ae04..0000000000000 --- a/src/libraries/Microsoft.Extensions.Options/gen/Resources.resx +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Type {0} already implements the Validate method - - - A type already includes an implementation of the `Validate` method - - - [OptionsValidator] cannot be applied to static class {0} - - - `OptionsValidatorAttribute` can't be applied to a static class - - - 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 - - - There is a circular type reference involving type {0} preventing it from being used for static validation - - - Unsupported circular references in model types - - - Type {0} does not implement the required IValidateOptions<{1}> interface - - - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - - - Can't apply validation attributes to private field or property {0} - - - Can't validate private fields or properties - - - Type {0} has no fields or properties to validate, referenced from member {1} - - - Type {0} has no fields or properties to validate, referenced by type {1} - - - A type has no fields or properties to validate - - - A member type has no fields or properties to validate - - - [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> - - - Member type is not enumerable - - - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - - - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - - - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - - - Member potentially missing enumerable validation - - - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight - - - Member potentially missing transitive validation - - - Validator type {0} doesn't have a parameterless constructor - - - Validators used for transitive or enumerable validation must have a constructor with no parameters - - diff --git a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj index 202e9435ce7f6..adfda8a3d1213 100644 --- a/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj +++ b/src/libraries/Microsoft.Extensions.Options/src/Microsoft.Extensions.Options.csproj @@ -30,4 +30,10 @@ + + + + From f20f8e6fd6ceec3aeba557d7c8b693e62a6b5e54 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Thu, 15 Jun 2023 16:56:41 -0700 Subject: [PATCH 03/13] Change the initialization to use ForAttributeWithMetadataName --- .../gen/EmitterBase.cs | 14 +- .../gen/Generator.cs | 22 +-- .../gen/GeneratorUtilities.cs | 131 ------------------ ...Extensions.Options.SourceGeneration.csproj | 1 - 4 files changed, 26 insertions(+), 142 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs diff --git a/src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs b/src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs index 3243038427c0a..890c9bc598989 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs @@ -8,6 +8,16 @@ namespace Microsoft.Extensions.Options.Generators { internal class EmitterBase { + public static string GeneratedCodeAttribute { get; } = $"global::System.CodeDom.Compiler.GeneratedCodeAttribute(" + + $"\"{typeof(EmitterBase).Assembly.GetName().Name}\", " + + $"\"{typeof(EmitterBase).Assembly.GetName().Version}\")"; + + public static string FilePreamble { get; } = @$" + // + #nullable enable + #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 + "; + private const int DefaultStringBuilderCapacity = 1024; private const int IndentChars = 4; @@ -25,7 +35,7 @@ public EmitterBase(bool emitPreamble = true) if (emitPreamble) { - Out(GeneratorUtilities.FilePreamble); + Out(FilePreamble); } } @@ -95,7 +105,7 @@ protected void OutEnumeration(IEnumerable e) protected void Out(char ch) => _ = _sb.Append(ch); protected void Indent() => _indent++; protected void Unindent() => _indent--; - protected void OutGeneratedCodeAttribute() => OutLn($"[{GeneratorUtilities.GeneratedCodeAttribute}]"); + protected void OutGeneratedCodeAttribute() => OutLn($"[{GeneratedCodeAttribute}]"); protected string Capture() => _sb.ToString(); } } diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs b/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs index d1e01d3583e18..52b44e0964931 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; @@ -14,17 +15,22 @@ namespace Microsoft.Extensions.Options.Generators [Generator] public class Generator : IIncrementalGenerator { - private static readonly HashSet _attributeNames = new() - { - SymbolLoader.OptionsValidatorAttribute, - }; - public void Initialize(IncrementalGeneratorInitializationContext context) { - GeneratorUtilities.Initialize(context, _attributeNames, HandleAnnotatedTypes); + IncrementalValuesProvider typeDeclarations = context.SyntaxProvider + .ForAttributeWithMetadataName( + SymbolLoader.OptionsValidatorAttribute, + (node, _) => node is TypeDeclarationSyntax, + (context, _) => context.TargetNode as TypeDeclarationSyntax) + .Where(static m => m is not null); + + IncrementalValueProvider<(Compilation, ImmutableArray)> compilationAndTypes = + context.CompilationProvider.Combine(typeDeclarations.Collect()); + + context.RegisterSourceOutput(compilationAndTypes, static (spc, source) => HandleAnnotatedTypes(source.Item1, source.Item2, spc)); } - private static void HandleAnnotatedTypes(Compilation compilation, IEnumerable nodes, SourceProductionContext context) + private static void HandleAnnotatedTypes(Compilation compilation, ImmutableArray types, SourceProductionContext context) { if (!SymbolLoader.TryLoad(compilation, out var symbolHolder)) { @@ -34,7 +40,7 @@ private static void HandleAnnotatedTypes(Compilation compilation, IEnumerable()); + var validatorTypes = parser.GetValidatorTypes(types); if (validatorTypes.Count > 0) { var emitter = new Emitter(); diff --git a/src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs b/src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs deleted file mode 100644 index 9b8c3aaf8e59b..0000000000000 --- a/src/libraries/Microsoft.Extensions.Options/gen/GeneratorUtilities.cs +++ /dev/null @@ -1,131 +0,0 @@ -// 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 Microsoft.CodeAnalysis; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Threading; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Microsoft.Extensions.Options.Generators -{ - internal static class GeneratorUtilities - { - public static string GeneratedCodeAttribute { get; } = $"global::System.CodeDom.Compiler.GeneratedCodeAttribute(" + - $"\"{typeof(GeneratorUtilities).Assembly.GetName().Name}\", " + - $"\"{typeof(GeneratorUtilities).Assembly.GetName().Version}\")"; - - public static string FilePreamble { get; } = @$" - // - #nullable enable - #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 - "; - - public static void Initialize( - IncrementalGeneratorInitializationContext context, - HashSet fullyQualifiedAttributeNames, - Action, SourceProductionContext> process) => Initialize(context, fullyQualifiedAttributeNames, x => x, process); - - public static void Initialize( - IncrementalGeneratorInitializationContext context, - HashSet fullyQualifiedAttributeNames, - Func transform, - Action, SourceProductionContext> process) - { - // strip the namespace prefix and the Attribute suffix - var shortAttributeNames = new HashSet(); - foreach (var n in fullyQualifiedAttributeNames) - { - var index = n.LastIndexOf('.') + 1; - _ = shortAttributeNames.Add(n.Substring(index, n.Length - index - "Attribute".Length)); - } - - var declarations = context.SyntaxProvider - .CreateSyntaxProvider( - (node, _) => Predicate(node, shortAttributeNames), - (gsc, ct) => Filter(gsc, fullyQualifiedAttributeNames, transform, ct)) - .Where(t => t is not null) - .Select((t, _) => t!); - - var compilationAndTypes = context.CompilationProvider.Combine(declarations.Collect()); - - context.RegisterSourceOutput(compilationAndTypes, (spc, source) => - { - var compilation = source.Left; - var nodes = source.Right; - - if (nodes.IsDefaultOrEmpty) - { - // nothing to do yet - return; - } - - process(compilation, nodes.Distinct(), spc); - }); - - static bool Predicate(SyntaxNode node, HashSet shortAttributeNames) - { - if (node.IsKind(SyntaxKind.Attribute)) - { - var attr = (AttributeSyntax)node; - - // see if we can trivially reject this node and avoid further work - if (attr.Name is IdentifierNameSyntax id) - { - return shortAttributeNames.Contains(id.Identifier.Text); - } - - // too complicated to check further, the filter will have to decide - return true; - } - - return false; - } - - static SyntaxNode? Filter(GeneratorSyntaxContext context, HashSet fullyQualifiedAttributeNames, Func transform, CancellationToken cancellationToken) - { - var attributeSyntax = (AttributeSyntax)context.Node; - - var ctor = context.SemanticModel.GetSymbolInfo(attributeSyntax, cancellationToken).Symbol as IMethodSymbol; - var attributeType = ctor?.ContainingType; - if (attributeType != null && fullyQualifiedAttributeNames.Contains(GetAttributeDisplayName(attributeType))) - { - var node = attributeSyntax.Parent?.Parent; - if (node != null) - { - return transform(node); - } - } - - return null; - } - - static string GetAttributeDisplayName(INamedTypeSymbol attributeType) - => attributeType.IsGenericType ? - attributeType.OriginalDefinition.ToDisplayString() : - attributeType.ToDisplayString(); - } - - /// - /// Reports will not be generated during design time to prevent file being written on every keystroke in VS. - /// References: - /// 1. - /// Design-time build. - /// 2. - /// Reading MSBuild Properties in Source Generators. - /// - /// . - /// The name of the MSBuild property that determines whether to produce a report. - /// bool value to indicate if reports should be generated. - public static bool ShouldGenerateReport(GeneratorExecutionContext context, string msBuildProperty) - { - _ = context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(msBuildProperty, out var generateFiles); - - return string.Equals(generateFiles, bool.TrueString, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj index 602c547dedee2..b7f2e01b8cc46 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj +++ b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj @@ -21,7 +21,6 @@ - From 86409c09ff670c51cde76fd86e3b02106a743d51 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Thu, 15 Jun 2023 18:52:37 -0700 Subject: [PATCH 04/13] Excluding tests on WASM --- .../SourceGenerationTests/EmitterTests.cs | 2 +- .../ParserTests.Enumeration.cs | 15 ++-- .../SourceGenerationTests/ParserTests.cs | 69 ++++++++++--------- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs index 44134625cd6c0..0d742b1c5b6b3 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs @@ -17,7 +17,7 @@ namespace Microsoft.Gen.OptionsValidation.Test; public class EmitterTests { - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task TestEmitter() { var sources = new List(); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs index 5663a16021c2d..2a2debaef03e8 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Options.Generators; using SourceGenerators.Tests; +using System; using System.Threading.Tasks; using Xunit; @@ -10,7 +11,7 @@ namespace Microsoft.Gen.OptionsValidation.Test; public partial class ParserTests { - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task CircularTypeReferencesInEnumeration() { var (d, _) = await RunGenerator(@" @@ -31,7 +32,7 @@ public partial class FirstValidator : IValidateOptions Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NotValidatorInEnumeration() { var (d, _) = await RunGenerator(@" @@ -61,7 +62,7 @@ public partial class SecondValidator Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NullValidatorInEnumeration() { var (d, _) = await RunGenerator(@" @@ -92,7 +93,7 @@ public partial class SecondValidator : IValidateOptions Assert.Equal(DiagDescriptors.NullValidatorType.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NoSimpleValidatorConstructorInEnumeration() { var (d, _) = await RunGenerator(@" @@ -129,7 +130,7 @@ public SecondValidator(int _) Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task CantValidateOpenGenericMembersInEnumeration() { var (d, _) = await RunGenerator(@" @@ -160,7 +161,7 @@ public partial class FirstValidator : IValidateOptions> Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[2].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ClosedGenericsInEnumeration() { var (d, _) = await RunGenerator(@" @@ -191,7 +192,7 @@ public partial class FirstValidator : IValidateOptions> Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[2].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NotEnumerable() { var (d, _) = await RunGenerator(@" diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs index 55e541f48fc3d..9b0dd62718e7c 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs @@ -1,7 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options.Generators; using SourceGenerators.Tests; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; @@ -9,17 +14,13 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.Options.Generators; using Xunit; namespace Microsoft.Gen.OptionsValidation.Test; public partial class ParserTests { - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task PotentiallyMissingAttributes() { var (d, _) = await RunGenerator(@" @@ -49,7 +50,7 @@ public partial class FirstValidator : IValidateOptions Assert.Equal(DiagDescriptors.PotentiallyMissingEnumerableValidation.Id, d[1].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task CircularTypeReferences() { var (d, _) = await RunGenerator(@" @@ -70,7 +71,7 @@ public partial class FirstValidator : IValidateOptions Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task InvalidValidatorInterface() { var (d, _) = await RunGenerator(@" @@ -101,7 +102,7 @@ public partial class SecondValidator Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NotValidator() { var (d, _) = await RunGenerator(@" @@ -131,7 +132,7 @@ public partial class SecondValidator Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ValidatorAlreadyImplementValidateFunction() { var (d, _) = await RunGenerator(@" @@ -169,7 +170,7 @@ public ValidateOptionsResult Validate(string name, SecondModel options) Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NullValidator() { var (d, _) = await RunGenerator(@" @@ -200,7 +201,7 @@ public partial class SecondValidator : IValidateOptions Assert.Equal(DiagDescriptors.NullValidatorType.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NoSimpleValidatorConstructor() { var (d, _) = await RunGenerator(@" @@ -237,7 +238,7 @@ public SecondValidator(int _) Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NoStaticValidator() { var (d, _) = await RunGenerator(@" @@ -257,7 +258,7 @@ public static partial class FirstValidator : IValidateOptions Assert.Equal(DiagDescriptors.CantBeStaticClass.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task BogusModelType() { var (d, _) = await RunGenerator(@" @@ -271,7 +272,7 @@ public partial class FirstValidator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task CantValidateOpenGenericMembers() { var (d, _) = await RunGenerator(@" @@ -302,7 +303,7 @@ public partial class FirstValidator : IValidateOptions> Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[2].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ClosedGenerics() { var (d, _) = await RunGenerator(@" @@ -338,7 +339,7 @@ public partial class FirstValidator : IValidateOptions> Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[3].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task NoEligibleMembers() { var (d, _) = await RunGenerator(@" @@ -370,7 +371,7 @@ public partial class SecondValidator : IValidateOptions Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, d[1].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task AlreadyImplemented() { var (d, _) = await RunGenerator(@" @@ -393,7 +394,7 @@ public void Validate(string name, FirstModel fm) Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldNotProduceInfoWhenTheClassHasABaseClass() { var (d, _) = await RunGenerator(@" @@ -418,7 +419,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldNotProduceInfoWhenTransitiveClassHasABaseClass() { var (d, _) = await RunGenerator(@" @@ -449,7 +450,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] [InlineData("bool")] [InlineData("int")] [InlineData("double")] @@ -484,7 +485,7 @@ public partial class Validator : IValidateOptions Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldProduceWarningWhenTheClassHasNoEligibleMembers() { var (d, _) = await RunGenerator(@" @@ -504,7 +505,7 @@ public partial class Validator : IValidateOptions Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, d[0].Id); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] [InlineData("private")] [InlineData("protected")] public async Task ShouldProduceWarningWhenTheClassMembersAreInaccessible(string accessModifier) @@ -529,7 +530,7 @@ public partial class Validator : IValidateOptions Assert.Equal("SYSLIB1206", d[0].Id); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldNotProduceErrorWhenMultipleValidationAnnotationsExist() { var (d, _) = await RunGenerator(@" @@ -549,7 +550,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldNotProduceErrorWhenDataTypeAttributesAreUsed() { var (d, _) = await RunGenerator(@" @@ -583,7 +584,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldNotProduceErrorWhenConstVariableIsUsedAsAttributeArgument() { var (d, _) = await RunGenerator(@" @@ -604,7 +605,7 @@ public partial class Validator : IValidateOptions } // Testing on all existing & eligible annotations extending ValidationAttribute that aren't used above - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldNotProduceAnyMessagesWhenExistingValidationsArePlaced() { var (d, _) = await RunGenerator(@" @@ -644,7 +645,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldNotProduceErrorWhenPropertiesAreUsedAsAttributeArgument() { var (d, _) = await RunGenerator(@" @@ -664,7 +665,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldSkipWhenOptionsValidatorAttributeDoesNotExist() { var (d, _) = await RunGenerator(@" @@ -684,7 +685,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldSkipAtrributeWhenAttributeSymbolCannotBeFound() { var (d, _) = await RunGenerator(@" @@ -706,7 +707,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldSkipAtrributeWhenAttributeSymbolIsNotBasedOnValidationAttribute() { var (d, _) = await RunGenerator(@" @@ -728,7 +729,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldAcceptAtrributeWhenAttributeIsInDifferentNamespace() { var (d, _) = await RunGenerator(@" @@ -754,7 +755,7 @@ public partial class Validator : IValidateOptions Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldHandleAtrributePropertiesOtherThanString() { var (d, _) = await RunGenerator(@" @@ -788,7 +789,7 @@ public TestAttribute() { Assert.Empty(d); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task ShouldStoreFloatValuesCorrectly() { var backupCulture = CultureInfo.CurrentCulture; @@ -819,7 +820,7 @@ public partial class Validator : IValidateOptions } } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] public async Task MultiModelValidatorGeneratesOnlyOnePartialTypeBlock() { var (d, sources) = await RunGenerator(@" From 9456bf5fad56ab1cbcd03fd1dfcdda6a36bc1392 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Fri, 16 Jun 2023 17:43:23 -0700 Subject: [PATCH 05/13] Address Martin's feedback --- .../gen/Emitter.cs | 20 ++++--- .../Baselines/NetCoreApp/Validators.g.cs | 52 +------------------ .../Baselines/NetFX/Validators.g.cs | 52 +------------------ .../SourceGenerationTests/EmitterTests.cs | 2 - 4 files changed, 11 insertions(+), 115 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs index ebf72a11b3f44..b632171936dc1 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs @@ -41,8 +41,6 @@ public string Emit( private void GenValidatorType(ValidatorType vt, ref Dictionary staticValidationAttributesDict, ref Dictionary staticValidatorsDict) { - OutLn("#pragma warning disable CS0618 // Type or member is obsolete"); - if (vt.Namespace.Length > 0) { OutLn($"namespace {vt.Namespace}"); @@ -282,9 +280,9 @@ private void GenTransitiveValidation(ValidatedMember vm, ref Dictionary #nullable enable #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 - #pragma warning disable CS0618 // Type or member is obsolete -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] internal sealed partial class __ThirdModelNoNamespaceValidator__ { /// @@ -27,7 +26,6 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ return builder.Build(); } } -#pragma warning disable CS0618 // Type or member is obsolete partial class FirstValidatorNoNamespace { /// @@ -61,7 +59,6 @@ partial class FirstValidatorNoNamespace return builder.Build(); } } -#pragma warning disable CS0618 // Type or member is obsolete partial class SecondValidatorNoNamespace { /// @@ -85,7 +82,6 @@ partial class SecondValidatorNoNamespace return builder.Build(); } } -#pragma warning disable CS0618 // Type or member is obsolete namespace CustomAttr { partial class FirstValidator @@ -115,7 +111,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -143,7 +138,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -170,7 +164,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { partial struct FirstValidator @@ -316,7 +309,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { partial struct SecondValidator @@ -343,7 +335,6 @@ partial struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Fields { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -371,7 +362,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Fields { partial struct FirstValidator @@ -405,7 +395,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Fields { partial struct SecondValidator @@ -432,7 +421,6 @@ partial struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace FileScopedNamespace { partial struct FirstValidator @@ -459,7 +447,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace FunnyStrings { partial struct FirstValidator @@ -485,7 +472,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Generics { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -513,7 +499,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Generics { partial class FirstValidator @@ -545,7 +530,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace MultiModelValidator { partial struct MultiValidator @@ -597,7 +581,6 @@ partial struct MultiValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -625,7 +608,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial record struct Container7 @@ -655,7 +637,6 @@ partial record struct FifthValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial class Container2 @@ -700,7 +681,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial struct Container6 @@ -730,7 +710,6 @@ partial struct FourthValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial class Container2 @@ -763,7 +742,6 @@ partial struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial record class Container4 @@ -796,7 +774,6 @@ partial struct ThirdValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RandomMembers { partial class FirstValidator @@ -823,7 +800,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -851,7 +827,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { partial record struct FirstValidator @@ -890,7 +865,6 @@ partial record struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { partial record struct SecondValidator @@ -917,7 +891,6 @@ partial record struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { partial record class ThirdValidator @@ -944,7 +917,6 @@ partial record class ThirdValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RepeatedTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -976,7 +948,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RepeatedTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1004,7 +975,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RepeatedTypes { partial class FirstValidator @@ -1053,7 +1023,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace SelfValidation { partial struct FirstValidator @@ -1081,7 +1050,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1108,7 +1076,6 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1135,7 +1102,6 @@ internal sealed partial class __RequiredAttributeModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1171,7 +1137,6 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class AttributePropertyModelValidator @@ -1201,7 +1166,6 @@ partial class AttributePropertyModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class ComplexModelValidator @@ -1233,7 +1197,6 @@ partial class ComplexModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class CustomTypeCustomValidationAttributeModelValidator @@ -1259,7 +1222,6 @@ partial class CustomTypeCustomValidationAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class CustomValidationAttributeModelValidator @@ -1285,7 +1247,6 @@ partial class CustomValidationAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class DataTypeAttributeModelValidator @@ -1311,7 +1272,6 @@ partial class DataTypeAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class DerivedModelValidator @@ -1345,7 +1305,6 @@ partial class DerivedModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class EmailAttributeModelValidator @@ -1371,7 +1330,6 @@ partial class EmailAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class LeafModelValidator @@ -1405,7 +1363,6 @@ partial class LeafModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class MultipleAttributeModelValidator @@ -1444,7 +1401,6 @@ partial class MultipleAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RangeAttributeModelDateValidator @@ -1470,7 +1426,6 @@ partial class RangeAttributeModelDateValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RangeAttributeModelDoubleValidator @@ -1496,7 +1451,6 @@ partial class RangeAttributeModelDoubleValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RangeAttributeModelIntValidator @@ -1522,7 +1476,6 @@ partial class RangeAttributeModelIntValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RegularExpressionAttributeModelValidator @@ -1548,7 +1501,6 @@ partial class RegularExpressionAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RequiredAttributeModelValidator @@ -1574,7 +1526,6 @@ partial class RequiredAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace ValueTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1602,7 +1553,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace ValueTypes { partial struct FirstValidator diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs index 452bf9bd63fd8..a5dd9cc473905 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs @@ -2,8 +2,7 @@ // #nullable enable #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 - #pragma warning disable CS0618 // Type or member is obsolete -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] internal sealed partial class __ThirdModelNoNamespaceValidator__ { /// @@ -27,7 +26,6 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ return builder.Build(); } } -#pragma warning disable CS0618 // Type or member is obsolete partial class FirstValidatorNoNamespace { /// @@ -61,7 +59,6 @@ partial class FirstValidatorNoNamespace return builder.Build(); } } -#pragma warning disable CS0618 // Type or member is obsolete partial class SecondValidatorNoNamespace { /// @@ -85,7 +82,6 @@ partial class SecondValidatorNoNamespace return builder.Build(); } } -#pragma warning disable CS0618 // Type or member is obsolete namespace CustomAttr { partial class FirstValidator @@ -115,7 +111,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -143,7 +138,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -170,7 +164,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { partial struct FirstValidator @@ -316,7 +309,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Enumeration { partial struct SecondValidator @@ -343,7 +335,6 @@ partial struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Fields { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -371,7 +362,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Fields { partial struct FirstValidator @@ -405,7 +395,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Fields { partial struct SecondValidator @@ -432,7 +421,6 @@ partial struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace FileScopedNamespace { partial struct FirstValidator @@ -459,7 +447,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace FunnyStrings { partial struct FirstValidator @@ -485,7 +472,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Generics { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -513,7 +499,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Generics { partial class FirstValidator @@ -545,7 +530,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace MultiModelValidator { partial struct MultiValidator @@ -597,7 +581,6 @@ partial struct MultiValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -625,7 +608,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial record struct Container7 @@ -655,7 +637,6 @@ partial record struct FifthValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial class Container2 @@ -700,7 +681,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial struct Container6 @@ -730,7 +710,6 @@ partial struct FourthValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial class Container2 @@ -763,7 +742,6 @@ partial struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace Nested { partial record class Container4 @@ -796,7 +774,6 @@ partial struct ThirdValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RandomMembers { partial class FirstValidator @@ -823,7 +800,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -851,7 +827,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { partial record struct FirstValidator @@ -890,7 +865,6 @@ partial record struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { partial record struct SecondValidator @@ -917,7 +891,6 @@ partial record struct SecondValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RecordTypes { partial record class ThirdValidator @@ -944,7 +917,6 @@ partial record class ThirdValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RepeatedTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -976,7 +948,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RepeatedTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1004,7 +975,6 @@ internal sealed partial class __ThirdModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace RepeatedTypes { partial class FirstValidator @@ -1053,7 +1023,6 @@ partial class FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace SelfValidation { partial struct FirstValidator @@ -1081,7 +1050,6 @@ partial struct FirstValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1108,7 +1076,6 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1135,7 +1102,6 @@ internal sealed partial class __RequiredAttributeModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1171,7 +1137,6 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class AttributePropertyModelValidator @@ -1201,7 +1166,6 @@ partial class AttributePropertyModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class ComplexModelValidator @@ -1233,7 +1197,6 @@ partial class ComplexModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class CustomTypeCustomValidationAttributeModelValidator @@ -1259,7 +1222,6 @@ partial class CustomTypeCustomValidationAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class CustomValidationAttributeModelValidator @@ -1285,7 +1247,6 @@ partial class CustomValidationAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class DataTypeAttributeModelValidator @@ -1311,7 +1272,6 @@ partial class DataTypeAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class DerivedModelValidator @@ -1345,7 +1305,6 @@ partial class DerivedModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class EmailAttributeModelValidator @@ -1371,7 +1330,6 @@ partial class EmailAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class LeafModelValidator @@ -1405,7 +1363,6 @@ partial class LeafModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class MultipleAttributeModelValidator @@ -1444,7 +1401,6 @@ partial class MultipleAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RangeAttributeModelDateValidator @@ -1470,7 +1426,6 @@ partial class RangeAttributeModelDateValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RangeAttributeModelDoubleValidator @@ -1496,7 +1451,6 @@ partial class RangeAttributeModelDoubleValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RangeAttributeModelIntValidator @@ -1522,7 +1476,6 @@ partial class RangeAttributeModelIntValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RegularExpressionAttributeModelValidator @@ -1548,7 +1501,6 @@ partial class RegularExpressionAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace TestClasses.OptionsValidation { partial class RequiredAttributeModelValidator @@ -1574,7 +1526,6 @@ partial class RequiredAttributeModelValidator } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace ValueTypes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] @@ -1602,7 +1553,6 @@ internal sealed partial class __SecondModelValidator__ } } } -#pragma warning disable CS0618 // Type or member is obsolete namespace ValueTypes { partial struct FirstValidator diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs index 0d742b1c5b6b3..fe3e007e0464d 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/EmitterTests.cs @@ -54,8 +54,6 @@ public async Task TestEmitter() string result = r[0].SourceText.ToString(); Assert.Equal(baseline, result); - // string golden = File.ReadAllText(@"generated/Microsoft.Extensions.Options.SourceGeneration/Microsoft.Extensions.Options.Generators.Generator/Validators.g.cs"); - // Assert.Equal(golden, result); #pragma warning restore RS1035 } } From f61cae64aa3afea092e92e9f72c4fc3ff26c411c Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Fri, 16 Jun 2023 18:24:51 -0700 Subject: [PATCH 06/13] Address Jeff's comments --- .../gen/Emitter.cs | 14 +-- .../gen/Parser.cs | 18 ++-- .../Baselines/NetCoreApp/Validators.g.cs | 86 ++++++++++--------- .../Baselines/NetFX/Validators.g.cs | 86 ++++++++++--------- 4 files changed, 111 insertions(+), 93 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs index b632171936dc1..31782f0f14d87 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs @@ -169,13 +169,13 @@ private void GenModelValidationMethod( OutLn(); } - if (vm.TransValidatorType != null) + if (vm.TransValidatorType is not null) { GenTransitiveValidation(vm, ref staticValidatorsDict); OutLn(); } - if (vm.EnumerationValidatorType != null) + if (vm.EnumerationValidatorType is not null) { GenEnumerationValidation(vm, ref staticValidatorsDict); OutLn(); @@ -279,7 +279,7 @@ private void GenTransitiveValidation(ValidatedMember vm, ref Dictionary GetValidatorTypes(IEnumerable GetValidatorTypes(IEnumerable(); var parent = typeDec.Parent as TypeDeclarationSyntax; - while (parent != null && IsAllowedKind(parent.Kind())) + while (parent is not null && IsAllowedKind(parent.Kind())) { parents.Add($"partial {GetTypeKeyword(parent)} {parent.Identifier}{parent.TypeParameterList} {parent.ConstraintClauses}"); parent = parent.Parent as TypeDeclarationSyntax; @@ -263,7 +263,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s foreach (var member in members) { var memberInfo = GetMemberInfo(member, speculate); - if (memberInfo != null) + if (memberInfo is not null) { if (member.DeclaredAccessibility != Accessibility.Public && member.DeclaredAccessibility != Accessibility.Internal) { @@ -287,7 +287,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s memberType = prop.Type; break; case IFieldSymbol field: - if (field.AssociatedSymbol != null) + if (field.AssociatedSymbol is not null) { // a backing field for a property, don't need those return null; @@ -309,7 +309,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s var transValidatorIsSynthetic = false; var enumerationValidatorIsSynthetic = false; - foreach (var attribute in member.GetAttributes().Where(a => a.AttributeClass != null)) + foreach (var attribute in member.GetAttributes().Where(a => a.AttributeClass is not null)) { var attributeType = attribute.AttributeClass!; var attrLoc = attribute.ApplicationSyntaxReference?.GetSyntax().GetLocation(); @@ -328,7 +328,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s if (attribute.ConstructorArguments.Length == 1) { var transValidatorType = attribute.ConstructorArguments[0].Value as INamedTypeSymbol; - if (transValidatorType != null) + if (transValidatorType is not null) { if (CanValidate(transValidatorType, memberType)) { @@ -391,7 +391,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s if (attribute.ConstructorArguments.Length == 1) { var enumerationValidatorType = attribute.ConstructorArguments[0].Value as INamedTypeSymbol; - if (enumerationValidatorType != null) + if (enumerationValidatorType is not null) { if (CanValidate(enumerationValidatorType, enumeratedType)) { @@ -464,7 +464,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s if (enumerationValidatorTypeName == null && speculate) { var enumeratedType = GetEnumeratedType(memberType); - if (enumeratedType != null) + if (enumeratedType is not null) { if (!HasOpenGenerics(enumeratedType, out var genericType)) { @@ -477,7 +477,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s } } - if (validationAttrs.Count > 0 || transValidatorTypeName != null || enumerationValidatorTypeName != null) + if (validationAttrs.Count > 0 || transValidatorTypeName is not null || enumerationValidatorTypeName is not null) { return new( member.Name, diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs index f264909317548..e9756b11da0df 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs @@ -46,12 +46,12 @@ partial class FirstValidatorNoNamespace builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V1.Validate(baseName + "P2", options.P2)); } - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::__ThirdModelNoNamespaceValidator__.Validate(baseName + "P3", options.P3)); } @@ -181,51 +181,54 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - if (options.P1 != null) + if (options.P1 is not null) { var count = 0; foreach (var o in options.P1) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count}]", o)); } else { - builder.AddError(baseName + $"P1[{count++}] is null"); + builder.AddError(baseName + $"P1[{count}] is null"); } + count++; } } - if (options.P2 != null) + if (options.P2 is not null) { var count = 0; foreach (var o in options.P2) { if (o is not null) { - builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count++}]", o)); + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count}]", o)); } else { - builder.AddError(baseName + $"P2[{count++}] is null"); + builder.AddError(baseName + $"P2[{count}] is null"); } + count++; } } - if (options.P3 != null) + if (options.P3 is not null) { var count = 0; foreach (var o in options.P3) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count}]", o)); } + count++; } } - if (options.P4 != null) + if (options.P4 is not null) { var count = 0; foreach (var o in options.P4) @@ -234,43 +237,46 @@ partial struct FirstValidator } } - if (options.P5 != null) + if (options.P5 is not null) { var count = 0; foreach (var o in options.P5) { if (o is not null) { - builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count++}]", o.Value)); + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count}]", o.Value)); } + count++; } } - if (options.P51 != null) + if (options.P51 is not null) { var count = 0; foreach (var o in options.P51) { if (o is not null) { - builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count++}]", o.Value)); + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count}]", o.Value)); } + count++; } } - if (options.P6 != null) + if (options.P6 is not null) { var count = 0; foreach (var o in options.P6.Value) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count}]", o)); } else { - builder.AddError(baseName + $"P6[{count++}] is null"); + builder.AddError(baseName + $"P6[{count}] is null"); } + count++; } } @@ -280,28 +286,30 @@ partial struct FirstValidator { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count}]", o)); } else { - builder.AddError(baseName + $"P7[{count++}] is null"); + builder.AddError(baseName + $"P7[{count}] is null"); } + count++; } } - if (options.P8 != null) + if (options.P8 is not null) { var count = 0; foreach (var o in options.P8.Value) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count}]", o)); } else { - builder.AddError(baseName + $"P8[{count++}] is null"); + builder.AddError(baseName + $"P8[{count}] is null"); } + count++; } } @@ -384,7 +392,7 @@ partial struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V3.Validate(baseName + "P2", options.P2)); } @@ -521,7 +529,7 @@ partial class FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::Generics.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); } @@ -552,7 +560,7 @@ partial struct MultiValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V4.Validate(baseName + "P2", options.P2)); } @@ -663,14 +671,14 @@ partial struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V5.Validate(baseName + "P2", options.P2)); } builder.AddResult(global::Nested.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); - if (options.P4 != null) + if (options.P4 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V6.Validate(baseName + "P4", options.P4)); } @@ -849,12 +857,12 @@ partial record struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V7.Validate(baseName + "P2", options.P2)); } - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V8.Validate(baseName + "P3", options.P3)); } @@ -939,7 +947,7 @@ internal sealed partial class __SecondModelValidator__ context.DisplayName = baseName + "P4"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - if (options.P4 != null) + if (options.P4 is not null) { builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4)); } @@ -996,7 +1004,7 @@ partial class FirstValidator context.DisplayName = baseName + "P1"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - if (options.P1 != null) + if (options.P1 is not null) { builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P1", options.P1)); } @@ -1005,7 +1013,7 @@ partial class FirstValidator context.DisplayName = baseName + "P2"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P2, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2)); } @@ -1014,7 +1022,7 @@ partial class FirstValidator context.DisplayName = baseName + "P3"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); } @@ -1128,7 +1136,7 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ context.DisplayName = baseName + "Val2"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val2, context)); - if (options.YetAnotherComplexVal != null) + if (options.YetAnotherComplexVal is not null) { builder.AddResult(global::TestClasses.OptionsValidation.__RangeAttributeModelDoubleValidator__.Validate(baseName + "YetAnotherComplexVal", options.YetAnotherComplexVal)); } @@ -1183,12 +1191,12 @@ partial class ComplexModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - if (options.ComplexVal != null) + if (options.ComplexVal is not null) { builder.AddResult(global::TestClasses.OptionsValidation.__RequiredAttributeModelValidator__.Validate(baseName + "ComplexVal", options.ComplexVal)); } - if (options.ValWithoutOptionsValidator != null) + if (options.ValWithoutOptionsValidator is not null) { builder.AddResult(global::TestClasses.OptionsValidation.__TypeWithoutOptionsValidatorValidator__.Validate(baseName + "ValWithoutOptionsValidator", options.ValWithoutOptionsValidator)); } @@ -1575,14 +1583,14 @@ partial struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2.Value)); } builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); - if (options.P4 != null) + if (options.P4 is not null) { builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P4", options.P4.Value)); } diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs index a5dd9cc473905..c288a2a25f611 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs @@ -46,12 +46,12 @@ partial class FirstValidatorNoNamespace builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V1.Validate(baseName + "P2", options.P2)); } - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::__ThirdModelNoNamespaceValidator__.Validate(baseName + "P3", options.P3)); } @@ -181,51 +181,54 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - if (options.P1 != null) + if (options.P1 is not null) { var count = 0; foreach (var o in options.P1) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count}]", o)); } else { - builder.AddError(baseName + $"P1[{count++}] is null"); + builder.AddError(baseName + $"P1[{count}] is null"); } + count++; } } - if (options.P2 != null) + if (options.P2 is not null) { var count = 0; foreach (var o in options.P2) { if (o is not null) { - builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count++}]", o)); + builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count}]", o)); } else { - builder.AddError(baseName + $"P2[{count++}] is null"); + builder.AddError(baseName + $"P2[{count}] is null"); } + count++; } } - if (options.P3 != null) + if (options.P3 is not null) { var count = 0; foreach (var o in options.P3) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count}]", o)); } + count++; } } - if (options.P4 != null) + if (options.P4 is not null) { var count = 0; foreach (var o in options.P4) @@ -234,43 +237,46 @@ partial struct FirstValidator } } - if (options.P5 != null) + if (options.P5 is not null) { var count = 0; foreach (var o in options.P5) { if (o is not null) { - builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count++}]", o.Value)); + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count}]", o.Value)); } + count++; } } - if (options.P51 != null) + if (options.P51 is not null) { var count = 0; foreach (var o in options.P51) { if (o is not null) { - builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count++}]", o.Value)); + builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count}]", o.Value)); } + count++; } } - if (options.P6 != null) + if (options.P6 is not null) { var count = 0; foreach (var o in options.P6.Value) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count}]", o)); } else { - builder.AddError(baseName + $"P6[{count++}] is null"); + builder.AddError(baseName + $"P6[{count}] is null"); } + count++; } } @@ -280,28 +286,30 @@ partial struct FirstValidator { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count}]", o)); } else { - builder.AddError(baseName + $"P7[{count++}] is null"); + builder.AddError(baseName + $"P7[{count}] is null"); } + count++; } } - if (options.P8 != null) + if (options.P8 is not null) { var count = 0; foreach (var o in options.P8.Value) { if (o is not null) { - builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count++}]", o)); + builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count}]", o)); } else { - builder.AddError(baseName + $"P8[{count++}] is null"); + builder.AddError(baseName + $"P8[{count}] is null"); } + count++; } } @@ -384,7 +392,7 @@ partial struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V3.Validate(baseName + "P2", options.P2)); } @@ -521,7 +529,7 @@ partial class FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::Generics.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); } @@ -552,7 +560,7 @@ partial struct MultiValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V4.Validate(baseName + "P2", options.P2)); } @@ -663,14 +671,14 @@ partial struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V5.Validate(baseName + "P2", options.P2)); } builder.AddResult(global::Nested.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); - if (options.P4 != null) + if (options.P4 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V6.Validate(baseName + "P4", options.P4)); } @@ -849,12 +857,12 @@ partial record struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V7.Validate(baseName + "P2", options.P2)); } - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V8.Validate(baseName + "P3", options.P3)); } @@ -939,7 +947,7 @@ internal sealed partial class __SecondModelValidator__ context.DisplayName = baseName + "P4"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - if (options.P4 != null) + if (options.P4 is not null) { builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4)); } @@ -996,7 +1004,7 @@ partial class FirstValidator context.DisplayName = baseName + "P1"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - if (options.P1 != null) + if (options.P1 is not null) { builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P1", options.P1)); } @@ -1005,7 +1013,7 @@ partial class FirstValidator context.DisplayName = baseName + "P2"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P2, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2)); } @@ -1014,7 +1022,7 @@ partial class FirstValidator context.DisplayName = baseName + "P3"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); - if (options.P3 != null) + if (options.P3 is not null) { builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P3", options.P3)); } @@ -1128,7 +1136,7 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ context.DisplayName = baseName + "Val2"; builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val2, context)); - if (options.YetAnotherComplexVal != null) + if (options.YetAnotherComplexVal is not null) { builder.AddResult(global::TestClasses.OptionsValidation.__RangeAttributeModelDoubleValidator__.Validate(baseName + "YetAnotherComplexVal", options.YetAnotherComplexVal)); } @@ -1183,12 +1191,12 @@ partial class ComplexModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - if (options.ComplexVal != null) + if (options.ComplexVal is not null) { builder.AddResult(global::TestClasses.OptionsValidation.__RequiredAttributeModelValidator__.Validate(baseName + "ComplexVal", options.ComplexVal)); } - if (options.ValWithoutOptionsValidator != null) + if (options.ValWithoutOptionsValidator is not null) { builder.AddResult(global::TestClasses.OptionsValidation.__TypeWithoutOptionsValidatorValidator__.Validate(baseName + "ValWithoutOptionsValidator", options.ValWithoutOptionsValidator)); } @@ -1575,14 +1583,14 @@ partial struct FirstValidator builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); - if (options.P2 != null) + if (options.P2 is not null) { builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2.Value)); } builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P3", options.P3)); - if (options.P4 != null) + if (options.P4 is not null) { builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P4", options.P4.Value)); } From 8e6c7a08caeb7c940b528307d95c0d42aa01c7fe Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Sat, 17 Jun 2023 12:59:35 -0700 Subject: [PATCH 07/13] Replace the calls of ValidationAttribute.GetValidationResult with Validator.TryValidateValue Instead of validating each attribute separately, instead we collect the list of the attributes we need to validate and then call Validator.TryValidateValue. This will guarantee performing the same validation order as the runtime. --- .../gen/Emitter.cs | 19 +- .../Baselines/NetCoreApp/Validators.g.cs | 646 +++++++++++++++--- .../Baselines/NetFX/Validators.g.cs | 646 +++++++++++++++--- 3 files changed, 1129 insertions(+), 182 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs index 31782f0f14d87..56879ece55b7a 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs @@ -18,6 +18,10 @@ internal sealed class Emitter : EmitterBase private const string StaticFieldHolderClassesNamespace = "__OptionValidationStaticInstances"; private const string StaticValidationAttributeHolderClassFQN = $"global::{StaticFieldHolderClassesNamespace}.{StaticValidationAttributeHolderClassName}"; private const string StaticValidatorHolderClassFQN = $"global::{StaticFieldHolderClassesNamespace}.{StaticValidatorHolderClassName}"; + private const string StaticListType = "global::System.Collections.Generic.List"; + private const string StaticValidationResultType = "global::System.ComponentModel.DataAnnotations.ValidationResult"; + private const string StaticValidationAttributeType = "global::System.ComponentModel.DataAnnotations.ValidationAttribute"; + private sealed record StaticFieldInfo(string FieldTypeFQN, int FieldOrder, string FieldName, IList InstantiationLines); public string Emit( @@ -159,6 +163,8 @@ private void GenModelValidationMethod( OutLn($"var baseName = (string.IsNullOrEmpty(name) ? \"{modelToValidate.SimpleName}\" : name) + \".\";"); OutLn($"var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();"); OutLn($"var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);"); + OutLn($"var validationResults = new {StaticListType}<{StaticValidationResultType}>();"); + OutLn($"var validationAttributes = new {StaticListType}<{StaticValidationAttributeType}>();"); OutLn(); foreach (var vm in modelToValidate.MembersToValidate) @@ -187,8 +193,7 @@ private void GenModelValidationMethod( OutCloseBrace(); } - private void GenMemberValidation(ValidatedMember vm, - ref Dictionary staticValidationAttributesDict) + private void GenMemberValidation(ValidatedMember vm, ref Dictionary staticValidationAttributesDict) { OutLn($"context.MemberName = \"{vm.Name}\";"); OutLn($"context.DisplayName = baseName + \"{vm.Name}\";"); @@ -196,9 +201,15 @@ private void GenMemberValidation(ValidatedMember vm, foreach (var attr in vm.ValidationAttributes) { var staticValidationAttributeInstance = GetOrAddStaticValidationAttribute(ref staticValidationAttributesDict, attr); - - OutLn($"builder.AddResult({StaticValidationAttributeHolderClassFQN}.{staticValidationAttributeInstance.FieldName}.GetValidationResult(options.{vm.Name}, context));"); + OutLn($"validationAttributes.Add({StaticValidationAttributeHolderClassFQN}.{staticValidationAttributeInstance.FieldName});"); } + + OutLn($"if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.{vm.Name}!, context, validationResults, validationAttributes))"); + OutOpenBrace(); + OutLn($"builder.AddResults(validationResults);"); + OutCloseBrace(); + OutLn($"validationResults.Clear();"); + OutLn($"validationAttributes.Clear();"); } private StaticFieldInfo GetOrAddStaticValidationAttribute(ref Dictionary staticValidationAttributesDict, ValidationAttributeInfo attr) diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs index e9756b11da0df..cbacc9dd48014 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs @@ -17,11 +17,19 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -40,11 +48,19 @@ partial class FirstValidatorNoNamespace var baseName = (string.IsNullOrEmpty(name) ? "FirstModelNoNamespace" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -73,11 +89,19 @@ partial class SecondValidatorNoNamespace var baseName = (string.IsNullOrEmpty(name) ? "SecondModelNoNamespace" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -98,14 +122,28 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A3.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A3); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "P2"; context.DisplayName = baseName + "P2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A4.GetValidationResult(options.P2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A4); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -128,11 +166,19 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -155,10 +201,18 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Value"; context.DisplayName = baseName + "Value"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A5.GetValidationResult(options.Value, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A5); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Value!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -180,6 +234,8 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); if (options.P1 is not null) { @@ -333,11 +389,19 @@ partial struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -360,11 +424,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -386,11 +458,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -419,11 +499,19 @@ partial struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -445,11 +533,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -471,10 +567,18 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A6.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A6); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -497,11 +601,19 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -523,11 +635,19 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P3 is not null) { @@ -554,11 +674,19 @@ partial struct MultiValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -579,11 +707,19 @@ partial struct MultiValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P3"; context.DisplayName = baseName + "P3"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P3, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -606,11 +742,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -634,11 +778,19 @@ partial record struct FifthValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -665,11 +817,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -707,11 +867,19 @@ partial struct FourthValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -738,11 +906,19 @@ partial struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -770,11 +946,19 @@ partial struct ThirdValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -798,11 +982,19 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -825,11 +1017,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -851,11 +1051,19 @@ partial record struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -889,11 +1097,19 @@ partial record struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -915,11 +1131,19 @@ partial record class ThirdValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -942,10 +1166,18 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P4 is not null) { @@ -973,11 +1205,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -999,10 +1239,18 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P1 is not null) { @@ -1011,7 +1259,13 @@ partial class FirstValidator context.MemberName = "P2"; context.DisplayName = baseName + "P2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -1020,7 +1274,13 @@ partial class FirstValidator context.MemberName = "P3"; context.DisplayName = baseName + "P3"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P3 is not null) { @@ -1047,10 +1307,18 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context)); @@ -1075,10 +1343,18 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1101,10 +1377,18 @@ internal sealed partial class __RequiredAttributeModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1127,14 +1411,28 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ var baseName = (string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.YetAnotherComplexVal is not null) { @@ -1161,14 +1459,28 @@ partial class AttributePropertyModelValidator var baseName = (string.IsNullOrEmpty(name) ? "AttributePropertyModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A9.GetValidationResult(options.Val1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A9); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A10.GetValidationResult(options.Val2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A10); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1190,6 +1502,8 @@ partial class ComplexModelValidator var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); if (options.ComplexVal is not null) { @@ -1221,10 +1535,18 @@ partial class CustomTypeCustomValidationAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A11.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A11); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1246,10 +1568,18 @@ partial class CustomValidationAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A12.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A12); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1271,10 +1601,18 @@ partial class DataTypeAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "DataTypeAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A13.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A13); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1296,18 +1634,38 @@ partial class DerivedModelValidator var baseName = (string.IsNullOrEmpty(name) ? "DerivedModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "VirtualValWithAttr"; context.DisplayName = baseName + "VirtualValWithAttr"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithAttr, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithAttr!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1329,10 +1687,18 @@ partial class EmailAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "EmailAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A14.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A14); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1354,18 +1720,38 @@ partial class LeafModelValidator var baseName = (string.IsNullOrEmpty(name) ? "LeafModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "VirtualValWithoutAttr"; context.DisplayName = baseName + "VirtualValWithoutAttr"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithoutAttr, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithoutAttr!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1387,23 +1773,49 @@ partial class MultipleAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "MultipleAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A15.GetValidationResult(options.Val1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A15); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val3"; context.DisplayName = baseName + "Val3"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A17.GetValidationResult(options.Val3, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A17); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val3!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val4"; context.DisplayName = baseName + "Val4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A18.GetValidationResult(options.Val4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A18); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1425,10 +1837,18 @@ partial class RangeAttributeModelDateValidator var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDate" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A19.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A19); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1450,10 +1870,18 @@ partial class RangeAttributeModelDoubleValidator var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1475,10 +1903,18 @@ partial class RangeAttributeModelIntValidator var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelInt" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1500,10 +1936,18 @@ partial class RegularExpressionAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A20.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A20); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1525,10 +1969,18 @@ partial class RequiredAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1551,11 +2003,19 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1577,11 +2037,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs index c288a2a25f611..eacaef8029bf2 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs @@ -17,11 +17,19 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -40,11 +48,19 @@ partial class FirstValidatorNoNamespace var baseName = (string.IsNullOrEmpty(name) ? "FirstModelNoNamespace" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -73,11 +89,19 @@ partial class SecondValidatorNoNamespace var baseName = (string.IsNullOrEmpty(name) ? "SecondModelNoNamespace" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -98,14 +122,28 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A3.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A3); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "P2"; context.DisplayName = baseName + "P2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A4.GetValidationResult(options.P2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A4); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -128,11 +166,19 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -155,10 +201,18 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Value"; context.DisplayName = baseName + "Value"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A5.GetValidationResult(options.Value, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A5); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Value!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -180,6 +234,8 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); if (options.P1 is not null) { @@ -333,11 +389,19 @@ partial struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -360,11 +424,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -386,11 +458,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -419,11 +499,19 @@ partial struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -445,11 +533,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -471,10 +567,18 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A6.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A6); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -497,11 +601,19 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -523,11 +635,19 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P3 is not null) { @@ -554,11 +674,19 @@ partial struct MultiValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -579,11 +707,19 @@ partial struct MultiValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P3"; context.DisplayName = baseName + "P3"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P3, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -606,11 +742,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -634,11 +778,19 @@ partial record struct FifthValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -665,11 +817,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -707,11 +867,19 @@ partial struct FourthValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -738,11 +906,19 @@ partial struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -770,11 +946,19 @@ partial struct ThirdValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -798,11 +982,19 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -825,11 +1017,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P6, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P6, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -851,11 +1051,19 @@ partial record struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -889,11 +1097,19 @@ partial record struct SecondValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -915,11 +1131,19 @@ partial record class ThirdValidator var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -942,10 +1166,18 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P4 is not null) { @@ -973,11 +1205,19 @@ internal sealed partial class __ThirdModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P5, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P5, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -999,10 +1239,18 @@ partial class FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P1 is not null) { @@ -1011,7 +1259,13 @@ partial class FirstValidator context.MemberName = "P2"; context.DisplayName = baseName + "P2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { @@ -1020,7 +1274,13 @@ partial class FirstValidator context.MemberName = "P3"; context.DisplayName = baseName + "P3"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P3, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P3 is not null) { @@ -1047,10 +1307,18 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context)); @@ -1075,10 +1343,18 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1101,10 +1377,18 @@ internal sealed partial class __RequiredAttributeModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1127,14 +1411,28 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ var baseName = (string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.YetAnotherComplexVal is not null) { @@ -1161,14 +1459,28 @@ partial class AttributePropertyModelValidator var baseName = (string.IsNullOrEmpty(name) ? "AttributePropertyModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A9.GetValidationResult(options.Val1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A9); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A10.GetValidationResult(options.Val2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A10); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1190,6 +1502,8 @@ partial class ComplexModelValidator var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); if (options.ComplexVal is not null) { @@ -1221,10 +1535,18 @@ partial class CustomTypeCustomValidationAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A11.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A11); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1246,10 +1568,18 @@ partial class CustomValidationAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A12.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A12); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1271,10 +1601,18 @@ partial class DataTypeAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "DataTypeAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A13.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A13); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1296,18 +1634,38 @@ partial class DerivedModelValidator var baseName = (string.IsNullOrEmpty(name) ? "DerivedModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "VirtualValWithAttr"; context.DisplayName = baseName + "VirtualValWithAttr"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithAttr, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithAttr!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1329,10 +1687,18 @@ partial class EmailAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "EmailAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A14.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A14); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1354,18 +1720,38 @@ partial class LeafModelValidator var baseName = (string.IsNullOrEmpty(name) ? "LeafModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "VirtualValWithoutAttr"; context.DisplayName = baseName + "VirtualValWithoutAttr"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.VirtualValWithoutAttr, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithoutAttr!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.DerivedVal, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1387,23 +1773,49 @@ partial class MultipleAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "MultipleAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A15.GetValidationResult(options.Val1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A15); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val2, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val3"; context.DisplayName = baseName + "Val3"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A17.GetValidationResult(options.Val3, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A17); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val3!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); context.MemberName = "Val4"; context.DisplayName = baseName + "Val4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A18.GetValidationResult(options.Val4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A18); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1425,10 +1837,18 @@ partial class RangeAttributeModelDateValidator var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDate" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A8.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1450,10 +1870,18 @@ partial class RangeAttributeModelDoubleValidator var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A7.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1475,10 +1903,18 @@ partial class RangeAttributeModelIntValidator var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelInt" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A16.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1500,10 +1936,18 @@ partial class RegularExpressionAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A19.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A19); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1525,10 +1969,18 @@ partial class RequiredAttributeModelValidator var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.Val, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1551,11 +2003,19 @@ internal sealed partial class __SecondModelValidator__ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P4, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P4, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); return builder.Build(); } @@ -1577,11 +2037,19 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A1.GetValidationResult(options.P1, context)); - builder.AddResult(global::__OptionValidationStaticInstances.__Attributes.A2.GetValidationResult(options.P1, context)); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + validationResults.Clear(); + validationAttributes.Clear(); if (options.P2 is not null) { From c18789c8b1839e3f01b948320ba5bd91dfaa7d83 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Sun, 18 Jun 2023 12:34:43 -0700 Subject: [PATCH 08/13] Avoid calling List.Clean and create the list with initial capacity --- .../gen/Emitter.cs | 23 +- .../Baselines/NetCoreApp/Validators.g.cs | 248 ++++++------------ .../Baselines/NetFX/Validators.g.cs | 248 ++++++------------ 3 files changed, 163 insertions(+), 356 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs index 56879ece55b7a..e933566f0962d 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs @@ -163,15 +163,22 @@ private void GenModelValidationMethod( OutLn($"var baseName = (string.IsNullOrEmpty(name) ? \"{modelToValidate.SimpleName}\" : name) + \".\";"); OutLn($"var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();"); OutLn($"var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);"); - OutLn($"var validationResults = new {StaticListType}<{StaticValidationResultType}>();"); - OutLn($"var validationAttributes = new {StaticListType}<{StaticValidationAttributeType}>();"); + + int capacity = modelToValidate.MembersToValidate.Max(static vm => vm.ValidationAttributes.Count); + if (capacity > 0) + { + OutLn($"var validationResults = new {StaticListType}<{StaticValidationResultType}>();"); + OutLn($"var validationAttributes = new {StaticListType}<{StaticValidationAttributeType}>({capacity});"); + } OutLn(); + bool cleanListsBeforeUse = false; foreach (var vm in modelToValidate.MembersToValidate) { if (vm.ValidationAttributes.Count > 0) { - GenMemberValidation(vm, ref staticValidationAttributesDict); + GenMemberValidation(vm, ref staticValidationAttributesDict, cleanListsBeforeUse); + cleanListsBeforeUse = true; OutLn(); } @@ -193,11 +200,17 @@ private void GenModelValidationMethod( OutCloseBrace(); } - private void GenMemberValidation(ValidatedMember vm, ref Dictionary staticValidationAttributesDict) + private void GenMemberValidation(ValidatedMember vm, ref Dictionary staticValidationAttributesDict, bool cleanListsBeforeUse) { OutLn($"context.MemberName = \"{vm.Name}\";"); OutLn($"context.DisplayName = baseName + \"{vm.Name}\";"); + if (cleanListsBeforeUse) + { + OutLn($"validationResults.Clear();"); + OutLn($"validationAttributes.Clear();"); + } + foreach (var attr in vm.ValidationAttributes) { var staticValidationAttributeInstance = GetOrAddStaticValidationAttribute(ref staticValidationAttributesDict, attr); @@ -208,8 +221,6 @@ private void GenMemberValidation(ValidatedMember vm, ref Dictionary staticValidationAttributesDict, ValidationAttributeInfo attr) diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs index cbacc9dd48014..bb5e6b021947e 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs @@ -18,7 +18,7 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -28,8 +28,6 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -49,7 +47,7 @@ partial class FirstValidatorNoNamespace var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -59,8 +57,6 @@ partial class FirstValidatorNoNamespace { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -90,7 +86,7 @@ partial class SecondValidatorNoNamespace var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -100,8 +96,6 @@ partial class SecondValidatorNoNamespace { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -123,7 +117,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -132,18 +126,16 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "P2"; context.DisplayName = baseName + "P2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A4); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -167,7 +159,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -177,8 +169,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -202,7 +192,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Value"; context.DisplayName = baseName + "Value"; @@ -211,8 +201,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -234,8 +222,6 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); if (options.P1 is not null) { @@ -390,7 +376,7 @@ partial struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -400,8 +386,6 @@ partial struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -425,7 +409,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -435,8 +419,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -459,7 +441,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -469,8 +451,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -500,7 +480,7 @@ partial struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -510,8 +490,6 @@ partial struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -534,7 +512,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -544,8 +522,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -568,7 +544,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -577,8 +553,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -602,7 +576,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -612,8 +586,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -636,7 +608,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -646,8 +618,6 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P3 is not null) { @@ -675,7 +645,7 @@ partial struct MultiValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -685,8 +655,6 @@ partial struct MultiValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -708,7 +676,7 @@ partial struct MultiValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P3"; context.DisplayName = baseName + "P3"; @@ -718,8 +686,6 @@ partial struct MultiValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -743,7 +709,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -753,8 +719,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -779,7 +743,7 @@ partial record struct FifthValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -789,8 +753,6 @@ partial record struct FifthValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -818,7 +780,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -828,8 +790,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -868,7 +828,7 @@ partial struct FourthValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -878,8 +838,6 @@ partial struct FourthValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -907,7 +865,7 @@ partial struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -917,8 +875,6 @@ partial struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -947,7 +903,7 @@ partial struct ThirdValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -957,8 +913,6 @@ partial struct ThirdValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -983,7 +937,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -993,8 +947,6 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1018,7 +970,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -1028,8 +980,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1052,7 +1002,7 @@ partial record struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -1062,8 +1012,6 @@ partial record struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -1098,7 +1046,7 @@ partial record struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -1108,8 +1056,6 @@ partial record struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1132,7 +1078,7 @@ partial record class ThirdValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -1142,8 +1088,6 @@ partial record class ThirdValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1167,7 +1111,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -1176,8 +1120,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P4 is not null) { @@ -1206,7 +1148,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -1216,8 +1158,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1240,7 +1180,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -1249,8 +1189,6 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P1 is not null) { @@ -1259,13 +1197,13 @@ partial class FirstValidator context.MemberName = "P2"; context.DisplayName = baseName + "P2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -1274,13 +1212,13 @@ partial class FirstValidator context.MemberName = "P3"; context.DisplayName = baseName + "P3"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P3 is not null) { @@ -1308,7 +1246,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -1317,8 +1255,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context)); @@ -1344,7 +1280,7 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1353,8 +1289,6 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1378,7 +1312,7 @@ internal sealed partial class __RequiredAttributeModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1387,8 +1321,6 @@ internal sealed partial class __RequiredAttributeModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1412,7 +1344,7 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; @@ -1421,18 +1353,16 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.YetAnotherComplexVal is not null) { @@ -1460,7 +1390,7 @@ partial class AttributePropertyModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; @@ -1469,18 +1399,16 @@ partial class AttributePropertyModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A10); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1502,8 +1430,6 @@ partial class ComplexModelValidator var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); if (options.ComplexVal is not null) { @@ -1536,7 +1462,7 @@ partial class CustomTypeCustomValidationAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1545,8 +1471,6 @@ partial class CustomTypeCustomValidationAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1569,7 +1493,7 @@ partial class CustomValidationAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1578,8 +1502,6 @@ partial class CustomValidationAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1602,7 +1524,7 @@ partial class DataTypeAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1611,8 +1533,6 @@ partial class DataTypeAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1635,7 +1555,7 @@ partial class DerivedModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; @@ -1644,28 +1564,26 @@ partial class DerivedModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "VirtualValWithAttr"; context.DisplayName = baseName + "VirtualValWithAttr"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithAttr!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1688,7 +1606,7 @@ partial class EmailAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1697,8 +1615,6 @@ partial class EmailAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1721,7 +1637,7 @@ partial class LeafModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "VirtualValWithoutAttr"; context.DisplayName = baseName + "VirtualValWithoutAttr"; @@ -1730,28 +1646,26 @@ partial class LeafModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1774,7 +1688,7 @@ partial class MultipleAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; @@ -1784,38 +1698,36 @@ partial class MultipleAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val3"; context.DisplayName = baseName + "Val3"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A17); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val3!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val4"; context.DisplayName = baseName + "Val4"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A18); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val4!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1838,7 +1750,7 @@ partial class RangeAttributeModelDateValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1847,8 +1759,6 @@ partial class RangeAttributeModelDateValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1871,7 +1781,7 @@ partial class RangeAttributeModelDoubleValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1880,8 +1790,6 @@ partial class RangeAttributeModelDoubleValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1904,7 +1812,7 @@ partial class RangeAttributeModelIntValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1913,8 +1821,6 @@ partial class RangeAttributeModelIntValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1937,7 +1843,7 @@ partial class RegularExpressionAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1946,8 +1852,6 @@ partial class RegularExpressionAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1970,7 +1874,7 @@ partial class RequiredAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1979,8 +1883,6 @@ partial class RequiredAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -2004,7 +1906,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -2014,8 +1916,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -2038,7 +1938,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -2048,8 +1948,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs index eacaef8029bf2..6c9adb5a2b159 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs @@ -18,7 +18,7 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -28,8 +28,6 @@ internal sealed partial class __ThirdModelNoNamespaceValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -49,7 +47,7 @@ partial class FirstValidatorNoNamespace var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -59,8 +57,6 @@ partial class FirstValidatorNoNamespace { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -90,7 +86,7 @@ partial class SecondValidatorNoNamespace var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -100,8 +96,6 @@ partial class SecondValidatorNoNamespace { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -123,7 +117,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -132,18 +126,16 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "P2"; context.DisplayName = baseName + "P2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A4); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -167,7 +159,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -177,8 +169,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -202,7 +192,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Value"; context.DisplayName = baseName + "Value"; @@ -211,8 +201,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -234,8 +222,6 @@ partial struct FirstValidator var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); if (options.P1 is not null) { @@ -390,7 +376,7 @@ partial struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -400,8 +386,6 @@ partial struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -425,7 +409,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -435,8 +419,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -459,7 +441,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -469,8 +451,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -500,7 +480,7 @@ partial struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -510,8 +490,6 @@ partial struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -534,7 +512,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -544,8 +522,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -568,7 +544,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -577,8 +553,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -602,7 +576,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -612,8 +586,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -636,7 +608,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -646,8 +618,6 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P3 is not null) { @@ -675,7 +645,7 @@ partial struct MultiValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -685,8 +655,6 @@ partial struct MultiValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -708,7 +676,7 @@ partial struct MultiValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P3"; context.DisplayName = baseName + "P3"; @@ -718,8 +686,6 @@ partial struct MultiValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -743,7 +709,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -753,8 +719,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -779,7 +743,7 @@ partial record struct FifthValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -789,8 +753,6 @@ partial record struct FifthValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -818,7 +780,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -828,8 +790,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -868,7 +828,7 @@ partial struct FourthValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -878,8 +838,6 @@ partial struct FourthValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -907,7 +865,7 @@ partial struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -917,8 +875,6 @@ partial struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -947,7 +903,7 @@ partial struct ThirdValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -957,8 +913,6 @@ partial struct ThirdValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -983,7 +937,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -993,8 +947,6 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1018,7 +970,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P6"; context.DisplayName = baseName + "P6"; @@ -1028,8 +980,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1052,7 +1002,7 @@ partial record struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -1062,8 +1012,6 @@ partial record struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -1098,7 +1046,7 @@ partial record struct SecondValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -1108,8 +1056,6 @@ partial record struct SecondValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1132,7 +1078,7 @@ partial record class ThirdValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -1142,8 +1088,6 @@ partial record class ThirdValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1167,7 +1111,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -1176,8 +1120,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P4 is not null) { @@ -1206,7 +1148,7 @@ internal sealed partial class __ThirdModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P5"; context.DisplayName = baseName + "P5"; @@ -1216,8 +1158,6 @@ internal sealed partial class __ThirdModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1240,7 +1180,7 @@ partial class FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -1249,8 +1189,6 @@ partial class FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P1 is not null) { @@ -1259,13 +1197,13 @@ partial class FirstValidator context.MemberName = "P2"; context.DisplayName = baseName + "P2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { @@ -1274,13 +1212,13 @@ partial class FirstValidator context.MemberName = "P3"; context.DisplayName = baseName + "P3"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P3 is not null) { @@ -1308,7 +1246,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -1317,8 +1255,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context)); @@ -1344,7 +1280,7 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1353,8 +1289,6 @@ internal sealed partial class __RangeAttributeModelDoubleValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1378,7 +1312,7 @@ internal sealed partial class __RequiredAttributeModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1387,8 +1321,6 @@ internal sealed partial class __RequiredAttributeModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1412,7 +1344,7 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; @@ -1421,18 +1353,16 @@ internal sealed partial class __TypeWithoutOptionsValidatorValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.YetAnotherComplexVal is not null) { @@ -1460,7 +1390,7 @@ partial class AttributePropertyModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; @@ -1469,18 +1399,16 @@ partial class AttributePropertyModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A10); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1502,8 +1430,6 @@ partial class ComplexModelValidator var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + "."; var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); - var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); if (options.ComplexVal is not null) { @@ -1536,7 +1462,7 @@ partial class CustomTypeCustomValidationAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1545,8 +1471,6 @@ partial class CustomTypeCustomValidationAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1569,7 +1493,7 @@ partial class CustomValidationAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1578,8 +1502,6 @@ partial class CustomValidationAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1602,7 +1524,7 @@ partial class DataTypeAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1611,8 +1533,6 @@ partial class DataTypeAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1635,7 +1555,7 @@ partial class DerivedModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; @@ -1644,28 +1564,26 @@ partial class DerivedModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "VirtualValWithAttr"; context.DisplayName = baseName + "VirtualValWithAttr"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithAttr!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1688,7 +1606,7 @@ partial class EmailAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1697,8 +1615,6 @@ partial class EmailAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1721,7 +1637,7 @@ partial class LeafModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "VirtualValWithoutAttr"; context.DisplayName = baseName + "VirtualValWithoutAttr"; @@ -1730,28 +1646,26 @@ partial class LeafModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "DerivedVal"; context.DisplayName = baseName + "DerivedVal"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1774,7 +1688,7 @@ partial class MultipleAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "Val1"; context.DisplayName = baseName + "Val1"; @@ -1784,38 +1698,36 @@ partial class MultipleAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val2"; context.DisplayName = baseName + "Val2"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val3"; context.DisplayName = baseName + "Val3"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A17); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val3!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); context.MemberName = "Val4"; context.DisplayName = baseName + "Val4"; + validationResults.Clear(); + validationAttributes.Clear(); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A18); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val4!, context, validationResults, validationAttributes)) { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1838,7 +1750,7 @@ partial class RangeAttributeModelDateValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1847,8 +1759,6 @@ partial class RangeAttributeModelDateValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1871,7 +1781,7 @@ partial class RangeAttributeModelDoubleValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1880,8 +1790,6 @@ partial class RangeAttributeModelDoubleValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1904,7 +1812,7 @@ partial class RangeAttributeModelIntValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1913,8 +1821,6 @@ partial class RangeAttributeModelIntValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1937,7 +1843,7 @@ partial class RegularExpressionAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1946,8 +1852,6 @@ partial class RegularExpressionAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -1970,7 +1874,7 @@ partial class RequiredAttributeModelValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); context.MemberName = "Val"; context.DisplayName = baseName + "Val"; @@ -1979,8 +1883,6 @@ partial class RequiredAttributeModelValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -2004,7 +1906,7 @@ internal sealed partial class __SecondModelValidator__ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P4"; context.DisplayName = baseName + "P4"; @@ -2014,8 +1916,6 @@ internal sealed partial class __SecondModelValidator__ { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); return builder.Build(); } @@ -2038,7 +1938,7 @@ partial struct FirstValidator var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List(); - var validationAttributes = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(2); context.MemberName = "P1"; context.DisplayName = baseName + "P1"; @@ -2048,8 +1948,6 @@ partial struct FirstValidator { builder.AddResults(validationResults); } - validationResults.Clear(); - validationAttributes.Clear(); if (options.P2 is not null) { From 8ea301d5d2ffe0c927b6349c707bb5350cc3e151 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Sun, 18 Jun 2023 13:35:55 -0700 Subject: [PATCH 09/13] Pass down the SematicModel from the generator to the parser --- .../gen/Generator.cs | 10 +++++----- .../gen/Parser.cs | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs b/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs index 52b44e0964931..b24f43b5170d3 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Generator.cs @@ -17,20 +17,20 @@ public class Generator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { - IncrementalValuesProvider typeDeclarations = context.SyntaxProvider + IncrementalValuesProvider<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)> typeDeclarations = context.SyntaxProvider .ForAttributeWithMetadataName( SymbolLoader.OptionsValidatorAttribute, (node, _) => node is TypeDeclarationSyntax, - (context, _) => context.TargetNode as TypeDeclarationSyntax) - .Where(static m => m is not null); + (context, _) => (TypeSyntax:context.TargetNode as TypeDeclarationSyntax, SemanticModel: context.SemanticModel)) + .Where(static m => m.TypeSyntax is not null); - IncrementalValueProvider<(Compilation, ImmutableArray)> compilationAndTypes = + IncrementalValueProvider<(Compilation, ImmutableArray<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)>)> compilationAndTypes = context.CompilationProvider.Combine(typeDeclarations.Collect()); context.RegisterSourceOutput(compilationAndTypes, static (spc, source) => HandleAnnotatedTypes(source.Item1, source.Item2, spc)); } - private static void HandleAnnotatedTypes(Compilation compilation, ImmutableArray types, SourceProductionContext context) + private static void HandleAnnotatedTypes(Compilation compilation, ImmutableArray<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)> types, SourceProductionContext context) { if (!SymbolLoader.TryLoad(compilation, out var symbolHolder)) { diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs index 10c6881a12d7f..4dd820159dca3 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs @@ -39,24 +39,25 @@ public Parser( _symbolHolder = symbolHolder; } - public IReadOnlyList GetValidatorTypes(IEnumerable classes) + public IReadOnlyList GetValidatorTypes(IEnumerable<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)> classes) { var results = new List(); - foreach (var group in classes.GroupBy(x => x.SyntaxTree)) + foreach (var group in classes.GroupBy(x => x.TypeSyntax.SyntaxTree)) { SemanticModel? sm = null; foreach (var typeDec in group) { + TypeDeclarationSyntax syntax = typeDec.TypeSyntax; _cancellationToken.ThrowIfCancellationRequested(); - sm ??= _compilation.GetSemanticModel(typeDec.SyntaxTree); + sm ??= typeDec.SemanticModel; - var validatorType = sm.GetDeclaredSymbol(typeDec) as ITypeSymbol; + var validatorType = sm.GetDeclaredSymbol(syntax) as ITypeSymbol; if (validatorType is not null) { if (validatorType.IsStatic) { - Diag(DiagDescriptors.CantBeStaticClass, typeDec.GetLocation()); + Diag(DiagDescriptors.CantBeStaticClass, syntax.GetLocation()); continue; } @@ -66,7 +67,7 @@ public IReadOnlyList GetValidatorTypes(IEnumerable GetValidatorTypes(IEnumerable GetValidatorTypes(IEnumerable GetValidatorTypes(IEnumerable(); - var parent = typeDec.Parent as TypeDeclarationSyntax; + var parent = syntax.Parent as TypeDeclarationSyntax; while (parent is not null && IsAllowedKind(parent.Kind())) { From 54a2f97af3e4b88f39ce3309fd451df0b8dc3d5c Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Sun, 18 Jun 2023 16:49:27 -0700 Subject: [PATCH 10/13] Add isolated unit test --- .../tests/SourceGeneration.Unit.Tests/Main.cs | 130 ++++++++++++++++++ ...Options.SourceGeneration.Unit.Tests.csproj | 35 +++++ 2 files changed, 165 insertions(+) create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj 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 new file mode 100644 index 0000000000000..e617bb4ffdf71 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs @@ -0,0 +1,130 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options.Generators; +using SourceGenerators.Tests; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Reflection; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Gen.OptionsValidation.Unit.Test; + +public class EmitterTests +{ + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task TestEmitterWithCustomValidator() + { + string source = """ + using System; + using System.ComponentModel.DataAnnotations; + using Microsoft.Extensions.Options; + + #nullable enable + + namespace HelloWorld + { + public class MyOptions + { + [Required] + public string Val1 { get; set; } = string.Empty; + + [Range(1, 3)] + public int Val2 { get; set; } + } + + [OptionsValidator] + public partial struct MyOptionsValidator : IValidateOptions + { + } + } + """; + + string generatedSource = """ + + // + #nullable enable + #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 + namespace HelloWorld +{ + partial struct MyOptionsValidator + { + /// + /// Validates a specific named options instance (or all when is ). + /// + /// The name of the options instance being validated. + /// The options instance. + /// Validation result. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::HelloWorld.MyOptions options) + { + var baseName = (string.IsNullOrEmpty(name) ? "MyOptions" : name) + "."; + var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder(); + var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); + var validationResults = new global::System.Collections.Generic.List(); + var validationAttributes = new global::System.Collections.Generic.List(1); + + context.MemberName = "Val1"; + context.DisplayName = baseName + "Val1"; + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + + context.MemberName = "Val2"; + context.DisplayName = baseName + "Val2"; + validationResults.Clear(); + validationAttributes.Clear(); + validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); + if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes)) + { + builder.AddResults(validationResults); + } + + return builder.Build(); + } + } +} +namespace __OptionValidationStaticInstances +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + file static class __Attributes + { + internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute(); + + internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A2 = new global::System.ComponentModel.DataAnnotations.RangeAttribute( + (int)1, + (int)3); + } +} +namespace __OptionValidationStaticInstances +{ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] + file static class __Validators + { + } +} + +"""; + + var (d, r) = await RoslynTestUtils.RunGenerator( + new Generator(), + new[] + { + Assembly.GetAssembly(typeof(RequiredAttribute))!, + Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!, + Assembly.GetAssembly(typeof(IValidateOptions))!, + }, + new List { source }) + .ConfigureAwait(false); + + Assert.Empty(d); + _ = Assert.Single(r); + + Assert.Equal(generatedSource.Replace("\r\n", "\n"), r[0].SourceText.ToString().Replace("\r\n", "\n")); + } +} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj new file mode 100644 index 0000000000000..b9b237ae09c76 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj @@ -0,0 +1,35 @@ + + + $(NetCoreAppCurrent);$(NetFrameworkMinimum) + $(MicrosoftCodeAnalysisVersion_4_4) + true + + true + + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER;ROSLYN_4_0_OR_GREATER + + + + + + + + + + + + + + + + + + + + + + + + + + From 9119332377c0ad245c0e761b61d67850151f6802 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Mon, 19 Jun 2023 18:38:01 -0700 Subject: [PATCH 11/13] Final fixes --- .../gen/Emitter.cs | 2 +- ...Extensions.Options.SourceGeneration.csproj | 2 +- .../tests/SourceGeneration.Unit.Tests/Main.cs | 1128 ++++++++++++++++- ...Options.SourceGeneration.Unit.Tests.csproj | 2 + .../Resources/Strings.resx | 201 +++ .../Baselines/NetCoreApp/Validators.g.cs | 4 +- .../Baselines/NetFX/Validators.g.cs | 4 +- .../ParserTests.Enumeration.cs | 215 ---- .../SourceGenerationTests/ParserTests.cs | 931 -------------- 9 files changed, 1331 insertions(+), 1158 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Resources/Strings.resx delete mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs delete mode 100644 src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs index e933566f0962d..91ad41a630bf6 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs @@ -95,7 +95,7 @@ private void GenStaticClassWithStaticReadonlyFields(IEnumerable OutOpenBrace(); OutGeneratedCodeAttribute(); - OutLn($"file static class {className}"); + OutLn($"internal static class {className}"); OutOpenBrace(); var staticValidationAttributes = staticFields diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj index b7f2e01b8cc46..143713f0b5d28 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj +++ b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj @@ -12,7 +12,7 @@ - + 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 e617bb4ffdf71..ad094f991803f 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 @@ -1,12 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Extensions.Options; using Microsoft.Extensions.Options.Generators; using SourceGenerators.Tests; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; +using System.Globalization; +using System.Linq; using System.Reflection; using System.Threading.Tasks; using Xunit; @@ -92,7 +97,7 @@ partial struct MyOptionsValidator namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] - file static class __Attributes + internal static class __Attributes { internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute(); @@ -104,14 +109,14 @@ file static class __Attributes namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] - file static class __Validators + internal static class __Validators { } } """; - var (d, r) = await RoslynTestUtils.RunGenerator( + var (diagnostics, generatedSources) = await RoslynTestUtils.RunGenerator( new Generator(), new[] { @@ -122,9 +127,1120 @@ file static class __Validators new List { source }) .ConfigureAwait(false); - Assert.Empty(d); - _ = Assert.Single(r); + Assert.Empty(diagnostics); + _ = Assert.Single(generatedSources); - Assert.Equal(generatedSource.Replace("\r\n", "\n"), r[0].SourceText.ToString().Replace("\r\n", "\n")); + Assert.Equal(generatedSource.Replace("\r\n", "\n"), generatedSources[0].SourceText.ToString().Replace("\r\n", "\n")); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task PotentiallyMissingAttributes() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public SecondModel? P1 { get; set; } + + [Required] + public System.Collections.Generic.IList? P2 { get; set; } + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + Assert.Equal(2, diagnostics.Count); + Assert.Equal(DiagDescriptors.PotentiallyMissingTransitiveValidation.Id, diagnostics[0].Id); + Assert.Equal(DiagDescriptors.PotentiallyMissingEnumerableValidation.Id, diagnostics[1].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task CircularTypeReferences() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public FirstModel? P1 { get; set; } + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task InvalidValidatorInterface() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NotValidator() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateObjectMembers(typeof(SecondValidator)] + public SecondModel? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + public partial class SecondValidator + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ValidatorAlreadyImplementValidateFunction() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + + [ValidateObjectMembers(typeof(SecondValidator)] + public SecondModel? P2; + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + public ValidateOptionsResult Validate(string name, SecondModel options) + { + throw new System.NotSupportedException(); + } + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NullValidator() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateObjectMembers(null!)] + public SecondModel? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.NullValidatorType.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NoSimpleValidatorConstructor() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + + [ValidateObjectMembers(typeof(SecondValidator)] + public SecondModel? P2; + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + public SecondValidator(int _) + { + } + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NoStaticValidator() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string P1; + } + + [OptionsValidator] + public static partial class FirstValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.CantBeStaticClass.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task BogusModelType() + { + var (diagnostics, _) = await RunGenerator(@" + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + // the generator doesn't produce any errors here, since the C# compiler will take care of it + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task CantValidateOpenGenericMembers() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public T? P1; + + [ValidateObjectMembers] + [Required] + public T[]? P2; + + [ValidateObjectMembers] + [Required] + public System.Collections.Generics.IList P3 = null!; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(3, diagnostics.Count); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[0].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[1].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[2].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ClosedGenerics() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public T? P1; + + [ValidateObjectMembers] + [Required] + public T[]? P2; + + [ValidateObjectMembers] + [Required] + public int[]? P3; + + [ValidateObjectMembers] + [Required] + public System.Collections.Generics.IList? P4; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(4, diagnostics.Count); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[1].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[2].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[3].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NoEligibleMembers() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateObjectMembers] + public SecondModel? P1; + } + + public class SecondModel + { + public string P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + } + "); + + Assert.Equal(2, diagnostics.Count); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id); + Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, diagnostics[1].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task AlreadyImplemented() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string One { get; set; } = string.Empty; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + public void Validate(string name, FirstModel fm) + { + } + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldNotProduceInfoWhenTheClassHasABaseClass() + { + var (diagnostics, _) = await RunGenerator(@" + public class Parent + { + [Required] + public string parentString { get; set; } + } + + public class Child : Parent + { + [Required] + public string childString { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldNotProduceInfoWhenTransitiveClassHasABaseClass() + { + var (diagnostics, _) = await RunGenerator(@" + public class Parent + { + [Required] + public string parentString { get; set; } + } + + public class Child : Parent + { + [Required] + public string childString { get; set; } + } + + public class MyOptions + { + [ValidateObjectMembers] + public Child childVal { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + [InlineData("bool")] + [InlineData("int")] + [InlineData("double")] + [InlineData("string")] + [InlineData("System.String")] + [InlineData("System.DateTime")] + public async Task ShouldProduceWarn_WhenTransitiveAttrMisused(string memberClass) + { + var (diagnostics, _) = await RunGenerator(@$" + public class InnerModel + {{ + [Required] + public string childString {{ get; set; }} + }} + + public class MyOptions + {{ + [Required] + public string simpleVal {{ get; set; }} + + [ValidateObjectMembers] + public {memberClass} complexVal {{ get; set; }} + }} + + [OptionsValidator] + public partial class Validator : IValidateOptions + {{ + }} + "); + + Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldProduceWarningWhenTheClassHasNoEligibleMembers() + { + var (diagnostics, _) = await RunGenerator(@" + public class Child + { + private string AccountName { get; set; } + public object Weight; + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, diagnostics[0].Id); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + [InlineData("private")] + [InlineData("protected")] + public async Task ShouldProduceWarningWhenTheClassMembersAreInaccessible(string accessModifier) + { + var (diagnostics, _) = await RunGenerator($@" + public class Model + {{ + [Required] + public string? PublicVal {{ get; set; }} + + [Required] + {accessModifier} string? Val {{ get; set; }} + }} + + [OptionsValidator] + public partial class Validator : IValidateOptions + {{ + }} + "); + + Assert.Single(diagnostics); + Assert.Equal("SYSLIB1206", diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldNotProduceErrorWhenMultipleValidationAnnotationsExist() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [MinLength(5)] + [MaxLength(15)] + public string Val9 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldNotProduceErrorWhenDataTypeAttributesAreUsed() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [CreditCard] + public string Val3 = """"; + + [EmailAddress] + public string Val6 { get; set; } + + [EnumDataType(typeof(string))] + public string Val7 { get; set; } + + [FileExtensions] + public string Val8 { get; set; } + + [Phone] + public string Val10 { get; set; } + + [Url] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldNotProduceErrorWhenConstVariableIsUsedAsAttributeArgument() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + private const int q = 5; + [Range(q, 10)] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + // Testing on all existing & eligible annotations extending ValidationAttribute that aren't used above + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldNotProduceAnyMessagesWhenExistingValidationsArePlaced() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [Required] + public string Val { get; set; } + + [Compare(""val"")] + public string Val2 { get; set; } + + [DataType(DataType.Password)] + public string _val5 = """"; + + [Range(5.1, 10.11)] + public string Val12 { get; set; } + + [Range(typeof(MemberDeclarationSyntax), ""1/2/2004"", ""3/4/2004"")] + public string Val14 { get; set; } + + [RegularExpression("""")] + public string Val15 { get; set; } + + [StringLength(5)] + public string Val16 { get; set; } + + [CustomValidation(typeof(MemberDeclarationSyntax), ""CustomMethod"")] + public string Val17 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldNotProduceErrorWhenPropertiesAreUsedAsAttributeArgument() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + private const int q = 5; + [Range(q, 10, ErrorMessage = ""ErrorMessage"")] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldSkipWhenOptionsValidatorAttributeDoesNotExist() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + private const int q = 5; + [Range(q, 10, ErrorMessage = ""ErrorMessage"")] + public string Val11 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + ", includeOptionValidatorReferences: false); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldSkipAtrributeWhenAttributeSymbolCannotBeFound() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [RandomTest] + public string Val11 { get; set; } + + [Range(1, 10, ErrorMessage = ""ErrorMessage"")] + public string Val12 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldSkipAtrributeWhenAttributeSymbolIsNotBasedOnValidationAttribute() + { + var (diagnostics, _) = await RunGenerator(@" + public class IValidateOptionsTestFile + { + [FilterUIHint(""MultiForeignKey"")] + public string Val11 { get; set; } + + [Range(1, 10, ErrorMessage = ""ErrorMessage"")] + public string Val12 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldAcceptAtrributeWhenAttributeIsInDifferentNamespace() + { + var (diagnostics, _) = await RunGenerator(@" + namespace Test { + public class IValidateOptionsTestFile + { + [Test] + public string Val11 { get; set; } + } + + [AttributeUsage(AttributeTargets.Class)] + public sealed class TestAttribute : ValidationAttribute + { + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + } + ", inNamespace: false); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldHandleAtrributePropertiesOtherThanString() + { + var (diagnostics, _) = await RunGenerator(@" + namespace Test { + public class IValidateOptionsTestFile + { + [Test(num = 5)] + public string Val11 { get; set; } + + [Required] + public string Val12 { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + } + + namespace System.ComponentModel.DataAnnotations { + [AttributeUsage(AttributeTargets.Class)] + public sealed class TestAttribute : ValidationAttribute + { + public int num { get; set; } + public TestAttribute() { + } + } + } + ", inNamespace: false); + + Assert.Empty(diagnostics); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ShouldStoreFloatValuesCorrectly() + { + var backupCulture = CultureInfo.CurrentCulture; + CultureInfo.CurrentCulture = new CultureInfo("ru-RU", false); + try + { + var (diagMessages, generatedResults) = await RunGenerator(@" + public class Model + { + [Range(-0.1, 1.3)] + public string Val { get; set; } + } + + [OptionsValidator] + public partial class Validator : IValidateOptions + { + } + "); + + Assert.Empty(diagMessages); + Assert.Single(generatedResults); + Assert.DoesNotContain("0,1", generatedResults[0].SourceText.ToString()); + Assert.DoesNotContain("1,3", generatedResults[0].SourceText.ToString()); + } + finally + { + CultureInfo.CurrentCulture = backupCulture; + } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task MultiModelValidatorGeneratesOnlyOnePartialTypeBlock() + { + var (diagnostics, sources) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string P1 { get; set; } + } + + public class SecondModel + { + [Required] + public string P2 { get; set; } + } + + public class ThirdModel + { + [Required] + public string P3 { get; set; } + } + + [OptionsValidator] + public partial class MultiValidator : IValidateOptions, IValidateOptions, IValidateOptions + { + } + "); + + var typeDeclarations = sources[0].SyntaxTree + .GetRoot() + .DescendantNodes() + .OfType() + .ToArray(); + + var multiValidatorTypeDeclarations = typeDeclarations + .Where(x => x.Identifier.ValueText == "MultiValidator") + .ToArray(); + + Assert.Single(multiValidatorTypeDeclarations); + + var validateMethodDeclarations = multiValidatorTypeDeclarations[0] + .DescendantNodes() + .OfType() + .Where(x => x.Identifier.ValueText == "Validate") + .ToArray(); + + Assert.Equal(3, validateMethodDeclarations.Length); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task CircularTypeReferencesInEnumeration() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateEnumeratedItems] + public FirstModel[]? P1 { get; set; } + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NotValidatorInEnumeration() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateEnumeratedItems(typeof(SecondValidator)] + public SecondModel[]? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + public partial class SecondValidator + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NullValidatorInEnumeration() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateEnumeratedItems(null!)] + public SecondModel[]? P1; + } + + public class SecondModel + { + [Required] + public string? P2; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.NullValidatorType.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NoSimpleValidatorConstructorInEnumeration() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + public string? P1; + + [ValidateEnumeratedItems(typeof(SecondValidator)] + public SecondModel[]? P2; + } + + public class SecondModel + { + [Required] + public string? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + + [OptionsValidator] + public partial class SecondValidator : IValidateOptions + { + public SecondValidator(int _) + { + } + } + "); + + _ = Assert.Single(diagnostics); + Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, diagnostics[0].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task CantValidateOpenGenericMembersInEnumeration() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateEnumeratedItems] + public T[]? P1; + + [ValidateEnumeratedItems] + [Required] + public T[]? P2; + + [ValidateEnumeratedItems] + [Required] + public System.Collections.Generic.IList P3 = null!; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(3, diagnostics.Count); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[0].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[1].Id); + Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[2].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task ClosedGenericsInEnumeration() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [ValidateEnumeratedItems] + [Required] + public T[]? P1; + + [ValidateEnumeratedItems] + [Required] + public int[]? P2; + + [ValidateEnumeratedItems] + [Required] + public System.Collections.Generic.IList? P3; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions> + { + } + "); + + Assert.Equal(3, diagnostics.Count); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[1].Id); + Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[2].Id); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public async Task NotEnumerable() + { + var (diagnostics, _) = await RunGenerator(@" + public class FirstModel + { + [Required] + [ValidateEnumeratedItems] + public int P1; + } + + [OptionsValidator] + public partial class FirstValidator : IValidateOptions + { + } + "); + + Assert.Equal(1, diagnostics.Count); + Assert.Equal(DiagDescriptors.NotEnumerableType.Id, diagnostics[0].Id); + } + + private static async Task<(IReadOnlyList diagnostics, ImmutableArray generatedSources)> RunGenerator( + string code, + bool wrap = true, + bool inNamespace = true, + bool includeOptionValidatorReferences = true, + bool includeSystemReferences = true, + bool includeOptionsReferences = true, + bool includeTransitiveReferences = true) + { + var text = code; + if (wrap) + { + var nspaceStart = "namespace Test {"; + var nspaceEnd = "}"; + if (!inNamespace) + { + nspaceStart = ""; + nspaceEnd = ""; + } + + text = $@" + {nspaceStart} + using System.ComponentModel.DataAnnotations; + using Microsoft.Extensions.Options.Validation; + using Microsoft.Shared.Data.Validation; + using Microsoft.Extensions.Options; + using Microsoft.CodeAnalysis.CSharp.Syntax; + {code} + {nspaceEnd} + "; + } + + var assemblies = new List { Assembly.GetAssembly(typeof(MemberDeclarationSyntax))! }; + + if (includeOptionValidatorReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!); + } + + if (includeSystemReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(RequiredAttribute))!); + } + + if (includeOptionsReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(IValidateOptions))!); + } + + if (includeTransitiveReferences) + { + assemblies.Add(Assembly.GetAssembly(typeof(Microsoft.Extensions.Options.ValidateObjectMembersAttribute))!); + } + + var result = await RoslynTestUtils.RunGenerator(new Generator(), assemblies.ToArray(), new[] { text }) + .ConfigureAwait(false); + + return result; } } diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj index b9b237ae09c76..c18245aa1b5f4 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Microsoft.Extensions.Options.SourceGeneration.Unit.Tests.csproj @@ -11,6 +11,8 @@ + + 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 new file mode 100644 index 0000000000000..5de24c6e4868f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Resources/Strings.resx @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ErrorMessageResourceName + + + Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + + + Member potentially missing enumerable validation + + + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + + + There is a circular type reference involving type {0} preventing it from being used for static validation + + + Unsupported circular references in model types + + + Can't apply validation attributes to private field or property {0} + + + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + + + Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + + + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + + + A member type has no fields or properties to validate + + + A type has no fields or properties to validate + + + Member type is not enumerable + + + Validator type {0} doesn't have a parameterless constructor + + + Type {0} does not implement the required IValidateOptions<{1}> interface + + + Validators used for transitive or enumerable validation must have a constructor with no parameters + + + Type {0} has no fields or properties to validate, referenced by type {1} + + + Type {0} has no fields or properties to validate, referenced from member {1} + + + A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + + + Can't validate private fields or properties + + + [OptionsValidator] cannot be applied to static class {0} + + + A type already includes an implementation of the `Validate` method + + + Type {0} already implements the Validate method + + + `OptionsValidatorAttribute` can't be applied to a static class + + + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + + + Member potentially missing transitive validation + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs index bb5e6b021947e..a78ca02c4b6ca 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs @@ -1968,7 +1968,7 @@ partial struct FirstValidator namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] - file static class __Attributes + internal static class __Attributes { internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute(); @@ -2059,7 +2059,7 @@ file static class __Attributes namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] - file static class __Validators + internal static class __Validators { internal static readonly global::SecondValidatorNoNamespace V1 = new global::SecondValidatorNoNamespace(); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs index 6c9adb5a2b159..daa65114c056a 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetFX/Validators.g.cs @@ -1968,7 +1968,7 @@ partial struct FirstValidator namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] - file static class __Attributes + internal static class __Attributes { internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute(); @@ -2051,7 +2051,7 @@ file static class __Attributes namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")] - file static class __Validators + internal static class __Validators { internal static readonly global::SecondValidatorNoNamespace V1 = new global::SecondValidatorNoNamespace(); diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs deleted file mode 100644 index 2a2debaef03e8..0000000000000 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.Enumeration.cs +++ /dev/null @@ -1,215 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Extensions.Options.Generators; -using SourceGenerators.Tests; -using System; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Gen.OptionsValidation.Test; - -public partial class ParserTests -{ - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task CircularTypeReferencesInEnumeration() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - [ValidateEnumeratedItems] - public FirstModel[]? P1 { get; set; } - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NotValidatorInEnumeration() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [ValidateEnumeratedItems(typeof(SecondValidator)] - public SecondModel[]? P1; - } - - public class SecondModel - { - [Required] - public string? P2; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - public partial class SecondValidator - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NullValidatorInEnumeration() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [ValidateEnumeratedItems(null!)] - public SecondModel[]? P1; - } - - public class SecondModel - { - [Required] - public string? P2; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - [OptionsValidator] - public partial class SecondValidator : IValidateOptions - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.NullValidatorType.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NoSimpleValidatorConstructorInEnumeration() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - public string? P1; - - [ValidateEnumeratedItems(typeof(SecondValidator)] - public SecondModel[]? P2; - } - - public class SecondModel - { - [Required] - public string? P3; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - [OptionsValidator] - public partial class SecondValidator : IValidateOptions - { - public SecondValidator(int _) - { - } - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task CantValidateOpenGenericMembersInEnumeration() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - [ValidateEnumeratedItems] - public T[]? P1; - - [ValidateEnumeratedItems] - [Required] - public T[]? P2; - - [ValidateEnumeratedItems] - [Required] - public System.Collections.Generic.IList P3 = null!; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions> - { - } - "); - - Assert.Equal(3, d.Count); - Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[0].Id); - Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[1].Id); - Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[2].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ClosedGenericsInEnumeration() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [ValidateEnumeratedItems] - [Required] - public T[]? P1; - - [ValidateEnumeratedItems] - [Required] - public int[]? P2; - - [ValidateEnumeratedItems] - [Required] - public System.Collections.Generic.IList? P3; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions> - { - } - "); - - Assert.Equal(3, d.Count); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[1].Id); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[2].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NotEnumerable() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - [ValidateEnumeratedItems] - public int P1; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - "); - - Assert.Equal(1, d.Count); - Assert.Equal(DiagDescriptors.NotEnumerableType.Id, d[0].Id); - } -} diff --git a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs deleted file mode 100644 index 9b0dd62718e7c..0000000000000 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.cs +++ /dev/null @@ -1,931 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.Options.Generators; -using SourceGenerators.Tests; -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.ComponentModel.DataAnnotations; -using System.Globalization; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Gen.OptionsValidation.Test; - -public partial class ParserTests -{ - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task PotentiallyMissingAttributes() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - public SecondModel? P1 { get; set; } - - [Required] - public System.Collections.Generic.IList? P2 { get; set; } - } - - public class SecondModel - { - [Required] - public string? P3; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - "); - - Assert.Equal(2, d.Count); - Assert.Equal(DiagDescriptors.PotentiallyMissingTransitiveValidation.Id, d[0].Id); - Assert.Equal(DiagDescriptors.PotentiallyMissingEnumerableValidation.Id, d[1].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task CircularTypeReferences() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - [ValidateObjectMembers] - public FirstModel? P1 { get; set; } - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task InvalidValidatorInterface() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - public string? P1; - } - - public class SecondModel - { - [Required] - public string? P2; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - [OptionsValidator] - public partial class SecondValidator - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NotValidator() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [ValidateObjectMembers(typeof(SecondValidator)] - public SecondModel? P1; - } - - public class SecondModel - { - [Required] - public string? P2; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - public partial class SecondValidator - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ValidatorAlreadyImplementValidateFunction() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - public string? P1; - - [ValidateObjectMembers(typeof(SecondValidator)] - public SecondModel? P2; - } - - public class SecondModel - { - [Required] - public string? P3; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - [OptionsValidator] - public partial class SecondValidator : IValidateOptions - { - public ValidateOptionsResult Validate(string name, SecondModel options) - { - throw new System.NotSupportedException(); - } - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NullValidator() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [ValidateObjectMembers(null!)] - public SecondModel? P1; - } - - public class SecondModel - { - [Required] - public string? P2; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - [OptionsValidator] - public partial class SecondValidator : IValidateOptions - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.NullValidatorType.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NoSimpleValidatorConstructor() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - public string? P1; - - [ValidateObjectMembers(typeof(SecondValidator)] - public SecondModel? P2; - } - - public class SecondModel - { - [Required] - public string? P3; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - [OptionsValidator] - public partial class SecondValidator : IValidateOptions - { - public SecondValidator(int _) - { - } - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NoStaticValidator() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - public string P1; - } - - [OptionsValidator] - public static partial class FirstValidator : IValidateOptions - { - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.CantBeStaticClass.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task BogusModelType() - { - var (d, _) = await RunGenerator(@" - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - "); - - // the generator doesn't produce any errors here, since the C# compiler will take care of it - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task CantValidateOpenGenericMembers() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - [ValidateObjectMembers] - public T? P1; - - [ValidateObjectMembers] - [Required] - public T[]? P2; - - [ValidateObjectMembers] - [Required] - public System.Collections.Generics.IList P3 = null!; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions> - { - } - "); - - Assert.Equal(3, d.Count); - Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[0].Id); - Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[1].Id); - Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, d[2].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ClosedGenerics() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - [ValidateObjectMembers] - public T? P1; - - [ValidateObjectMembers] - [Required] - public T[]? P2; - - [ValidateObjectMembers] - [Required] - public int[]? P3; - - [ValidateObjectMembers] - [Required] - public System.Collections.Generics.IList? P4; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions> - { - } - "); - - Assert.Equal(4, d.Count); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[1].Id); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[2].Id); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[3].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task NoEligibleMembers() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - [ValidateObjectMembers] - public SecondModel? P1; - } - - public class SecondModel - { - public string P2; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - } - - [OptionsValidator] - public partial class SecondValidator : IValidateOptions - { - } - "); - - Assert.Equal(2, d.Count); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); - Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, d[1].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task AlreadyImplemented() - { - var (d, _) = await RunGenerator(@" - public class FirstModel - { - [Required] - public string One { get; set; } = string.Empty; - } - - [OptionsValidator] - public partial class FirstValidator : IValidateOptions - { - public void Validate(string name, FirstModel fm) - { - } - } - "); - - _ = Assert.Single(d); - Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldNotProduceInfoWhenTheClassHasABaseClass() - { - var (d, _) = await RunGenerator(@" - public class Parent - { - [Required] - public string parentString { get; set; } - } - - public class Child : Parent - { - [Required] - public string childString { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldNotProduceInfoWhenTransitiveClassHasABaseClass() - { - var (d, _) = await RunGenerator(@" - public class Parent - { - [Required] - public string parentString { get; set; } - } - - public class Child : Parent - { - [Required] - public string childString { get; set; } - } - - public class MyOptions - { - [ValidateObjectMembers] - public Child childVal { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - [InlineData("bool")] - [InlineData("int")] - [InlineData("double")] - [InlineData("string")] - [InlineData("System.String")] - [InlineData("System.DateTime")] - public async Task ShouldProduceWarn_WhenTransitiveAttrMisused(string memberClass) - { - var (d, _) = await RunGenerator(@$" - public class InnerModel - {{ - [Required] - public string childString {{ get; set; }} - }} - - public class MyOptions - {{ - [Required] - public string simpleVal {{ get; set; }} - - [ValidateObjectMembers] - public {memberClass} complexVal {{ get; set; }} - }} - - [OptionsValidator] - public partial class Validator : IValidateOptions - {{ - }} - "); - - Assert.Single(d); - Assert.Equal(DiagDescriptors.NoEligibleMember.Id, d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldProduceWarningWhenTheClassHasNoEligibleMembers() - { - var (d, _) = await RunGenerator(@" - public class Child - { - private string AccountName { get; set; } - public object Weight; - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Single(d); - Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, d[0].Id); - } - - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - [InlineData("private")] - [InlineData("protected")] - public async Task ShouldProduceWarningWhenTheClassMembersAreInaccessible(string accessModifier) - { - var (d, _) = await RunGenerator($@" - public class Model - {{ - [Required] - public string? PublicVal {{ get; set; }} - - [Required] - {accessModifier} string? Val {{ get; set; }} - }} - - [OptionsValidator] - public partial class Validator : IValidateOptions - {{ - }} - "); - - Assert.Single(d); - Assert.Equal("SYSLIB1206", d[0].Id); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldNotProduceErrorWhenMultipleValidationAnnotationsExist() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - [MinLength(5)] - [MaxLength(15)] - public string Val9 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldNotProduceErrorWhenDataTypeAttributesAreUsed() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - [CreditCard] - public string Val3 = """"; - - [EmailAddress] - public string Val6 { get; set; } - - [EnumDataType(typeof(string))] - public string Val7 { get; set; } - - [FileExtensions] - public string Val8 { get; set; } - - [Phone] - public string Val10 { get; set; } - - [Url] - public string Val11 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldNotProduceErrorWhenConstVariableIsUsedAsAttributeArgument() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - private const int q = 5; - [Range(q, 10)] - public string Val11 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - // Testing on all existing & eligible annotations extending ValidationAttribute that aren't used above - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldNotProduceAnyMessagesWhenExistingValidationsArePlaced() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - [Required] - public string Val { get; set; } - - [Compare(""val"")] - public string Val2 { get; set; } - - [DataType(DataType.Password)] - public string _val5 = """"; - - [Range(5.1, 10.11)] - public string Val12 { get; set; } - - [Range(typeof(MemberDeclarationSyntax), ""1/2/2004"", ""3/4/2004"")] - public string Val14 { get; set; } - - [RegularExpression("""")] - public string Val15 { get; set; } - - [StringLength(5)] - public string Val16 { get; set; } - - [CustomValidation(typeof(MemberDeclarationSyntax), ""CustomMethod"")] - public string Val17 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldNotProduceErrorWhenPropertiesAreUsedAsAttributeArgument() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - private const int q = 5; - [Range(q, 10, ErrorMessage = ""ErrorMessage"")] - public string Val11 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldSkipWhenOptionsValidatorAttributeDoesNotExist() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - private const int q = 5; - [Range(q, 10, ErrorMessage = ""ErrorMessage"")] - public string Val11 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - ", includeOptionValidatorReferences: false); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldSkipAtrributeWhenAttributeSymbolCannotBeFound() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - [RandomTest] - public string Val11 { get; set; } - - [Range(1, 10, ErrorMessage = ""ErrorMessage"")] - public string Val12 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldSkipAtrributeWhenAttributeSymbolIsNotBasedOnValidationAttribute() - { - var (d, _) = await RunGenerator(@" - public class IValidateOptionsTestFile - { - [FilterUIHint(""MultiForeignKey"")] - public string Val11 { get; set; } - - [Range(1, 10, ErrorMessage = ""ErrorMessage"")] - public string Val12 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldAcceptAtrributeWhenAttributeIsInDifferentNamespace() - { - var (d, _) = await RunGenerator(@" - namespace Test { - public class IValidateOptionsTestFile - { - [Test] - public string Val11 { get; set; } - } - - [AttributeUsage(AttributeTargets.Class)] - public sealed class TestAttribute : ValidationAttribute - { - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - } - ", inNamespace: false); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldHandleAtrributePropertiesOtherThanString() - { - var (d, _) = await RunGenerator(@" - namespace Test { - public class IValidateOptionsTestFile - { - [Test(num = 5)] - public string Val11 { get; set; } - - [Required] - public string Val12 { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - } - - namespace System.ComponentModel.DataAnnotations { - [AttributeUsage(AttributeTargets.Class)] - public sealed class TestAttribute : ValidationAttribute - { - public int num { get; set; } - public TestAttribute() { - } - } - } - ", inNamespace: false); - - Assert.Empty(d); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task ShouldStoreFloatValuesCorrectly() - { - var backupCulture = CultureInfo.CurrentCulture; - CultureInfo.CurrentCulture = new CultureInfo("ru-RU", false); - try - { - var (diagMessages, generatedResults) = await RunGenerator(@" - public class Model - { - [Range(-0.1, 1.3)] - public string Val { get; set; } - } - - [OptionsValidator] - public partial class Validator : IValidateOptions - { - } - "); - - Assert.Empty(diagMessages); - Assert.Single(generatedResults); - Assert.DoesNotContain("0,1", generatedResults[0].SourceText.ToString()); - Assert.DoesNotContain("1,3", generatedResults[0].SourceText.ToString()); - } - finally - { - CultureInfo.CurrentCulture = backupCulture; - } - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] - public async Task MultiModelValidatorGeneratesOnlyOnePartialTypeBlock() - { - var (d, sources) = await RunGenerator(@" - public class FirstModel - { - [Required] - public string P1 { get; set; } - } - - public class SecondModel - { - [Required] - public string P2 { get; set; } - } - - public class ThirdModel - { - [Required] - public string P3 { get; set; } - } - - [OptionsValidator] - public partial class MultiValidator : IValidateOptions, IValidateOptions, IValidateOptions - { - } - "); - - var typeDeclarations = sources[0].SyntaxTree - .GetRoot() - .DescendantNodes() - .OfType() - .ToArray(); - - var multiValidatorTypeDeclarations = typeDeclarations - .Where(x => x.Identifier.ValueText == "MultiValidator") - .ToArray(); - - Assert.Single(multiValidatorTypeDeclarations); - - var validateMethodDeclarations = multiValidatorTypeDeclarations[0] - .DescendantNodes() - .OfType() - .Where(x => x.Identifier.ValueText == "Validate") - .ToArray(); - - Assert.Equal(3, validateMethodDeclarations.Length); - } - - private static async Task<(IReadOnlyList diagnostics, ImmutableArray generatedSources)> RunGenerator( - string code, - bool wrap = true, - bool inNamespace = true, - bool includeOptionValidatorReferences = true, - bool includeSystemReferences = true, - bool includeOptionsReferences = true, - bool includeTransitiveReferences = true) - { - var text = code; - if (wrap) - { - var nspaceStart = "namespace Test {"; - var nspaceEnd = "}"; - if (!inNamespace) - { - nspaceStart = ""; - nspaceEnd = ""; - } - - text = $@" - {nspaceStart} - using System.ComponentModel.DataAnnotations; - using Microsoft.Extensions.Options.Validation; - using Microsoft.Shared.Data.Validation; - using Microsoft.Extensions.Options; - using Microsoft.CodeAnalysis.CSharp.Syntax; - {code} - {nspaceEnd} - "; - } - - var assemblies = new List { Assembly.GetAssembly(typeof(MemberDeclarationSyntax))! }; - - if (includeOptionValidatorReferences) - { - assemblies.Add(Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!); - } - - if (includeSystemReferences) - { - assemblies.Add(Assembly.GetAssembly(typeof(RequiredAttribute))!); - } - - if (includeOptionsReferences) - { - assemblies.Add(Assembly.GetAssembly(typeof(IValidateOptions))!); - } - - if (includeTransitiveReferences) - { - assemblies.Add(Assembly.GetAssembly(typeof(Microsoft.Extensions.Options.ValidateObjectMembersAttribute))!); - } - - var result = await RoslynTestUtils.RunGenerator(new Generator(), assemblies.ToArray(), new[] { text }) - .ConfigureAwait(false); - - return result; - } -} From c98e5fc6ee8ee525a6283b4a2b75e17d9eaa90c5 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Tue, 20 Jun 2023 08:50:44 -0700 Subject: [PATCH 12/13] Fix resource messages --- .../gen/Resources/Strings.resx | 106 +++++++++--------- .../gen/Resources/xlf/Strings.cs.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.de.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.es.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.fr.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.it.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.ja.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.ko.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.pl.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.pt-BR.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.ru.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.tr.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.zh-Hans.xlf | 104 ++++++++--------- .../gen/Resources/xlf/Strings.zh-Hant.xlf | 104 ++++++++--------- .../Resources/Strings.resx | 106 +++++++++--------- .../Resources/Strings.resx | 106 +++++++++--------- 16 files changed, 835 insertions(+), 835 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx index d9bae1523ae04..021f345f58cae 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Options/gen/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -118,81 +118,81 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Type {0} already implements the Validate method + 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] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation + 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 + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {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} + Type {0} has no fields or properties to validate, referenced from member {1}. - Type {0} has no fields or properties to validate, referenced by type {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. - A member type has no fields or properties to validate + A member 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] 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 + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + 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 + 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.cs.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.cs.xlf index 57d16e1551253..a27619874a770 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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.de.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.de.xlf index 5d004505ad1fe..1a2543583fd4f 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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.es.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.es.xlf index 608258bbfa7b4..ba26cf8cb3e90 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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.fr.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.fr.xlf index 0be945ff1400c..748bf1cbda2b7 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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.it.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.it.xlf index a146a705363cd..386b07ab9ff25 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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.ja.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ja.xlf index e7fe4e78472e0..1f4ccf0f7c868 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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 689728aa09597..283d22eedebe7 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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 6e7fd341996f1..cfa99a0d18363 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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.pt-BR.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.pt-BR.xlf index e7b8a0f69064e..80eb423892678 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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.ru.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.ru.xlf index 9317984bebcaa..7c01d660f80f0 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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 fa5feb3d2b603..4c7a25edb284c 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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-Hans.xlf b/src/libraries/Microsoft.Extensions.Options/gen/Resources/xlf/Strings.zh-Hans.xlf index 41f798ce9dd85..46de6fae73a5f 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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 04ac3af78908d..3b7ddf599ceeb 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 @@ -3,133 +3,133 @@ - Type {0} already implements the Validate method - Type {0} already implements the Validate method + Type {0} already implements the Validate method. + 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 + 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] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. + [OptionsValidator] cannot be applied to static class {0}. - `OptionsValidatorAttribute` can't be applied to a static class - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. + 'OptionsValidatorAttribute' can't be applied to a static class. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {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 - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - There is a circular type reference involving type {0} preventing it from being used for static validation - There is a circular type reference involving type {0} preventing it from being used for static validation + There is a circular type reference involving type {0} preventing it from being used for static validation. + 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 + Unsupported circular references in model types. + Unsupported circular references in model types. - Type {0} does not implement the required IValidateOptions<{1}> interface - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. + Type {0} does not implement the required IValidateOptions<{1}> interface. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't apply validation attributes to private field or property {0} - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {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 + 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} - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {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 + 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} - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {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 + 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] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement 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 + Member type is not enumerable. + Member type is not enumerable. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight. + 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 + 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 - Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. + 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 + Member potentially missing transitive validation. + Member potentially missing transitive validation. - Validator type {0} doesn't have a parameterless constructor - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. + 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 + 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/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Resources/Strings.resx index 5de24c6e4868f..1673d4621545b 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 @@ -1,17 +1,17 @@  - @@ -121,81 +121,81 @@ ErrorMessageResourceName - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. - There is a circular type reference involving type {0} preventing it from being used for static validation + 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. - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {0}. - [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}. - A member type has no fields or properties to validate + A member type has no fields or properties to validate. - A type has no fields or properties to validate + A type has no fields or properties to validate. - Member type is not enumerable + Member type is not enumerable. - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. - 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. - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {1}. - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {1}. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't validate private fields or properties + Can't validate private fields or properties. - [OptionsValidator] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. - A type already includes an implementation of the `Validate` method + A type already includes an implementation of the 'Validate' method. - Type {0} already implements the Validate method + Type {0} already implements the Validate method. - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Member potentially missing transitive validation + Member potentially missing transitive validation. \ 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 5de24c6e4868f..1673d4621545b 100644 --- a/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -121,81 +121,81 @@ ErrorMessageResourceName - Can't use `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types + Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types. - Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight + 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 + Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight. - There is a circular type reference involving type {0} preventing it from being used for static validation + 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. - Can't apply validation attributes to private field or property {0} + Can't apply validation attributes to private field or property {0}. - [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T> + [ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>. - Null validator type specified for the `ValidateObjectMembersAttribute` or `ValidateEnumeratedItemsAttribute` attributes + Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes. - Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0} + Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}. - A member type has no fields or properties to validate + A member type has no fields or properties to validate. - A type has no fields or properties to validate + A type has no fields or properties to validate. - Member type is not enumerable + Member type is not enumerable. - Validator type {0} doesn't have a parameterless constructor + Validator type {0} doesn't have a parameterless constructor. - Type {0} does not implement the required IValidateOptions<{1}> interface + Type {0} does not implement the required IValidateOptions<{1}> interface. - 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. - Type {0} has no fields or properties to validate, referenced by type {1} + Type {0} has no fields or properties to validate, referenced by type {1}. - Type {0} has no fields or properties to validate, referenced from member {1} + Type {0} has no fields or properties to validate, referenced from member {1}. - A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface + A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface. - Can't validate private fields or properties + Can't validate private fields or properties. - [OptionsValidator] cannot be applied to static class {0} + [OptionsValidator] cannot be applied to static class {0}. - A type already includes an implementation of the `Validate` method + A type already includes an implementation of the 'Validate' method. - Type {0} already implements the Validate method + Type {0} already implements the Validate method. - `OptionsValidatorAttribute` can't be applied to a static class + 'OptionsValidatorAttribute' can't be applied to a static class. - Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes + Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes. - Member potentially missing transitive validation + Member potentially missing transitive validation. \ No newline at end of file From ec2c6e467479ed09bda12612b22e04133f3b2bbb Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Tue, 20 Jun 2023 11:48:31 -0700 Subject: [PATCH 13/13] Address more feedback --- docs/project/list-of-diagnostics.md | 19 ++++++++++++++++++- ...Extensions.Options.SourceGeneration.csproj | 2 +- .../gen/Parser.cs | 4 ++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 2d1eab1db0293..c3732de3b02a1 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -235,7 +235,24 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL | __`SYSLIB1116`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | | __`SYSLIB1117`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | | __`SYSLIB1118`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | - +| __`SYSLIB1201`__ | Options validation generator: Can't use 'ValidateObjectMembersAttribute' or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types. | +| __`SYSLIB1202`__ | Options validation generator: A member type has no fields or properties to validate. | +| __`SYSLIB1203`__ | Options validation generator: A type has no fields or properties to validate. | +| __`SYSLIB1204`__ | Options validation generator: A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface. | +| __`SYSLIB1205`__ | Options validation generator: A type already includes an implementation of the 'Validate' method. | +| __`SYSLIB1206`__ | Options validation generator: Can't validate private fields or properties. | +| __`SYSLIB1207`__ | Options validation generator: Member type is not enumerable. | +| __`SYSLIB1208`__ | Options validation generator: Validators used for transitive or enumerable validation must have a constructor with no parameters. | +| __`SYSLIB1209`__ | Options validation generator: `OptionsValidatorAttribute` can't be applied to a static class. | +| __`SYSLIB1210`__ | Options validation generator: Null validator type specified for the `ValidateObjectMembersAttribute` or 'ValidateEnumeratedItemsAttribute' attributes. | +| __`SYSLIB1211`__ | Options validation generator: Unsupported circular references in model types. | +| __`SYSLIB1212`__ | Options validation generator: Member potentially missing transitive validation. | +| __`SYSLIB1213`__ | Options validation generator: Member potentially missing enumerable validation. | +| __`SYSLIB1214`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* | +| __`SYSLIB1215`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* | +| __`SYSLIB1216`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* | +| __`SYSLIB1217`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* | +| __`SYSLIB1218`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* | ### Diagnostic Suppressions (`SYSLIBSUPPRESS****`) diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj index 143713f0b5d28..12bc4a7c4d1e4 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj +++ b/src/libraries/Microsoft.Extensions.Options/gen/Microsoft.Extensions.Options.SourceGeneration.csproj @@ -16,6 +16,7 @@ + @@ -30,6 +31,5 @@ - diff --git a/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs index 4dd820159dca3..2a9215c676071 100644 --- a/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs +++ b/src/libraries/Microsoft.Extensions.Options/gen/Parser.cs @@ -431,7 +431,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s // pop the stack _ = _visitedModelTypes.Remove(enumeratedType.WithNullableAnnotation(NullableAnnotation.None)); } - else if (DerivesFrom(attributeType, _symbolHolder.ValidationAttributeSymbol)) + else if (ConvertTo(attributeType, _symbolHolder.ValidationAttributeSymbol)) { var validationAttr = new ValidationAttributeInfo(attributeType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); validationAttrs.Add(validationAttr); @@ -540,7 +540,7 @@ private List GetMembersToValidate(ITypeSymbol modelType, bool s return "global::" + (result.Namespace.Length > 0 ? result.Namespace + "." + result.Name : result.Name); } - private bool DerivesFrom(ITypeSymbol source, ITypeSymbol dest) + private bool ConvertTo(ITypeSymbol source, ITypeSymbol dest) { var conversion = _compilation.ClassifyConversion(source, dest); return conversion.IsReference && conversion.IsImplicit;