Skip to content

Simplify the generated code from ValidationsGenerator#67630

Open
Youssef1313 wants to merge 4 commits into
mainfrom
dev/ygerges/simplify-val
Open

Simplify the generated code from ValidationsGenerator#67630
Youssef1313 wants to merge 4 commits into
mainfrom
dev/ygerges/simplify-val

Conversation

@Youssef1313

Copy link
Copy Markdown
Member

{PR title}

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Summary of the changes (Less than 80 chars)

Description

{Detail}

Fixes #{bug number} (in this specific format)

Copilot AI review requested due to automatic review settings July 7, 2026 10:22
@Youssef1313 Youssef1313 force-pushed the dev/ygerges/simplify-val branch from ca9a987 to 3308ec8 Compare July 7, 2026 10:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR simplifies source-generated validation output by removing generated overrides/caches for type-level validation attributes and shifting responsibility to the runtime ValidatableTypeInfo base implementation. It also updates the generator test snapshots to reflect the new generated output.

Changes:

  • Changed ValidatableTypeInfo.GetValidationAttributes() from abstract to virtual and added a default reflection-based implementation.
  • Simplified generated output by removing the generated GetValidationAttributes() override and the generated type-attribute cache helper.
  • Updated many generator snapshot baselines accordingly.

Reviewed changes

Copilot reviewed 43 out of 43 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Validation/src/ValidatableTypeInfo.cs Makes GetValidationAttributes() virtual and provides a default reflection-based implementation.
src/Validation/src/PublicAPI.Unshipped.txt Adds the new virtual ValidatableTypeInfo.GetValidationAttributes() API entry.
src/Validation/gen/Emitters/ValidationsGenerator.Emitter.cs Stops emitting the type-level GetValidationAttributes() override and removes the generated type-attribute cache method.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.ValidatesPropertiesWithJsonIgnoreWhenWritingConditions#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.ValidatesInternalTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.SkipsNonReadableAndStaticProperties#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.SkipsIndexerPropertiesOnTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.SkipsFileLocalTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.SkipsClassesWithNonAccessibleTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.DoesNotEmitForExemptTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.DoesNotEmit_ForSkipValidationAttribute_OnRecordProperties#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.DoesNotEmit_ForSkipValidationAttribute_OnEndpointParameters#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.DoesNotEmit_ForSkipValidationAttribute_OnClassProperties#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateValidationAttributesOnClasses#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateTypeWithParsableProperties#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateRecursiveTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateRecordTypesWithAttribute#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateRecordTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateRecordStructTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidatePolymorphicTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateParameters#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateMultipleNamespaces#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateIValidatableObject#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateIValidatableObject_WithoutPropertyValidations#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateComplexTypesWithJsonIgnore#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateComplexTypes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanValidateClassTypesWithAttribute#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanUseBothFrameworkAndGeneratedValidatableTypeAttributes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanGenerateWhenAddValidationCalledMultipleTimes#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorTests.CanDiscoverGeneratedValidatableTypeAttribute#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.TypeDisplayName_WithResourceType#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.TypeDisplayName_WithNameOnly#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.TypeDisplayName_WithDisplayNameAttribute#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.RecordPropertyDisplayName_WithResourceType#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.RecordPropertyDisplayName_WithNameOnly#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.RecordPropertyDisplayName_LiteralOnConstructorParameter#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.PropertyDisplayName_WithResourceType#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.PropertyDisplayName_WithoutDisplayAttribute_UsesPropertyName#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.PropertyDisplayName_WithNameOnly#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.PropertyDisplayName_WithDisplayNameAttribute#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.PropertyDisplayName_WithControlCharacters_EmitsValidLiteral#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.ParameterDisplayName_WithResourceType#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.
src/Validation/test/Microsoft.Extensions.Validation.GeneratorTests/snapshots/ValidationsGeneratorDisplayNameTests.ParameterDisplayName_WithNameOnly#ValidatableInfoResolver.g.verified.cs Snapshot update for new generated resolver/type info output.

Comment thread src/Validation/src/ValidatableTypeInfo.cs Outdated
Comment thread src/Validation/src/PublicAPI.Unshipped.txt
@Youssef1313 Youssef1313 marked this pull request as draft July 7, 2026 11:49
@Youssef1313 Youssef1313 marked this pull request as ready for review July 7, 2026 18:51
@Youssef1313 Youssef1313 added area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc feature-validation Issues related to model validation in minimal and controller-based APIs labels Jul 7, 2026
@Youssef1313 Youssef1313 requested a review from oroztocil July 7, 2026 18:51
@@ -1,495 +1,500 @@
// Licensed to the .NET Foundation under one or more agreements.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a line-ending switch in this file that create a long spurious diff.

}

{{GeneratedCodeAttribute}}
file static class DisplayAttributeCache

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets also remove the DisplayAttributeCache and simply store the DisplayAttribute instance in PropertyResourceDisplayName/TypeResourceDisplayName. These are created at most once per cached type info.

/// <returns>An array of validation attributes to apply to this property.</returns>
protected abstract ValidationAttribute[] GetValidationAttributes();
protected virtual ValidationAttribute[] GetValidationAttributes()
=> _validationAttributes;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I said to remove the use of Lazy<T>, but maybe we could have a simple

protected virtual ValidationAttribute[] GetValidationAttributes()
        => _validationAttributes ?? = GetValidationAttributesCore();

This way a derived implementation that overrides GetValidationAttributes can avoid calling the reflection-based GetValidationAttributesCore completely.

var results = new List<ValidationAttribute>();

// Get attributes from the property
var property = Property;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following test needs to be fixed to conform with the new throwing DeclaredOnly property access:

Microsoft.Extensions.Validation.Tests.ValidatableTypeInfoTests.TryFindProperty_LocalDeclarationShadowsInheritedProperty

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc feature-validation Issues related to model validation in minimal and controller-based APIs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants