Skip to content

Commit f1f768f

Browse files
committed
tmp
1 parent 53a1a5a commit f1f768f

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

src/Validation/gen/Parsers/ValidationsGenerator.AttributeParser.cs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ internal ImmutableArray<ValidatableType> TransformValidatableTypeWithAttribute(G
2525
var wellKnownTypes = WellKnownTypes.GetOrCreate(context.SemanticModel.Compilation);
2626
if (TryExtractValidatableType((ITypeSymbol)context.TargetSymbol, wellKnownTypes, ref validatableTypes, ref visitedTypes))
2727
{
28-
return [..validatableTypes];
28+
return [.. validatableTypes];
2929
}
3030
return [];
3131
}
3232

33-
internal static bool ShouldTransformSymbolWithValidatableTypeAttribute(SyntaxNode syntaxNode, CancellationToken _)
33+
internal static bool ShouldTransformSymbolWithEmbeddedValidatableTypeAttribute(SyntaxNode syntaxNode, CancellationToken _)
3434
{
3535
// Only process class and record declarations
3636
if (syntaxNode is not (ClassDeclarationSyntax or RecordDeclarationSyntax))
@@ -54,7 +54,10 @@ internal static bool ShouldTransformSymbolWithValidatableTypeAttribute(SyntaxNod
5454
return false;
5555
}
5656

57-
internal ImmutableArray<ValidatableType> TransformValidatableTypeWithValidatableTypeAttribute(GeneratorSyntaxContext context, CancellationToken cancellationToken)
57+
internal ImmutableArray<ValidatableType> TransformValidatableTypeWithEmbeddedValidatableTypeAttribute(
58+
GeneratorSyntaxContext context,
59+
GeneratorSettings settings,
60+
CancellationToken cancellationToken)
5861
{
5962
if (context.Node is not (ClassDeclarationSyntax or RecordDeclarationSyntax))
6063
{
@@ -67,8 +70,9 @@ internal ImmutableArray<ValidatableType> TransformValidatableTypeWithValidatable
6770
return [];
6871
}
6972

70-
// Check if the type has a ValidatableTypeAttribute (framework or auto-generated)
71-
if (!HasValidatableTypeAttribute(typeSymbol))
73+
var validatableTypeAttributeName = $"{settings.RootNamespace}.ValidatableTypeAttribute";
74+
// Check if the type has a ValidatableTypeAttribute (auto-generated)
75+
if (!HasValidatableTypeAttribute(typeSymbol, validatableTypeAttributeName))
7276
{
7377
return [];
7478
}
@@ -79,7 +83,7 @@ internal ImmutableArray<ValidatableType> TransformValidatableTypeWithValidatable
7983

8084
if (TryExtractValidatableType(typeSymbol, wellKnownTypes, ref validatableTypes, ref visitedTypes))
8185
{
82-
return [..validatableTypes];
86+
return [.. validatableTypes];
8387
}
8488
return [];
8589
}
@@ -92,7 +96,7 @@ private static bool IsValidatableTypeAttribute(AttributeSyntax attribute)
9296
name.EndsWith(".ValidatableTypeAttribute", StringComparison.Ordinal);
9397
}
9498

95-
private static bool HasValidatableTypeAttribute(ITypeSymbol typeSymbol)
99+
private static bool HasValidatableTypeAttribute(ITypeSymbol typeSymbol, string validatableTypeAttributeName)
96100
{
97101
foreach (var attr in typeSymbol.GetAttributes())
98102
{
@@ -103,16 +107,15 @@ private static bool HasValidatableTypeAttribute(ITypeSymbol typeSymbol)
103107
}
104108

105109
var name = attributeClass.Name;
106-
var fullName = attributeClass.ToDisplayString();
107-
108-
// Check for framework attribute
109-
if (fullName == "Microsoft.Extensions.Validation.ValidatableTypeAttribute")
110+
var namespaceName = attributeClass.ContainingNamespace.ToDisplayString();
111+
var fullName = $"{namespaceName}.{name}";
112+
if (!string.Equals(fullName, validatableTypeAttributeName, StringComparison.Ordinal))
110113
{
111-
return true;
114+
continue;
112115
}
113116

114117
// Check for auto-generated attribute (any namespace)
115-
if (name == "ValidatableTypeAttribute")
118+
if (name == validatableTypeAttributeName)
116119
{
117120
// Additional check: ensure it's marked with [Embedded] to confirm it's auto-generated
118121
foreach (var embeddedAttr in attributeClass.GetAttributes())

src/Validation/gen/ValidationsGenerator.cs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Collections.Immutable;
56
using System.Linq;
7+
using Microsoft.AspNetCore.App.Analyzers.Infrastructure;
68
using Microsoft.CodeAnalysis;
79

810
namespace Microsoft.Extensions.Validation;
@@ -33,23 +35,49 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
3335
predicate: FindAddValidation,
3436
transform: TransformAddValidation
3537
);
38+
3639
// Extract types that have been marked with [ValidatableType].
3740
// This handles both the framework attribute and the auto-generated attribute.
38-
var validatableTypesWithAttribute = context.SyntaxProvider.CreateSyntaxProvider(
39-
predicate: ShouldTransformSymbolWithValidatableTypeAttribute,
40-
transform: TransformValidatableTypeWithValidatableTypeAttribute
41-
).Where(types => types.Length > 0);
41+
var validatableTypesWithAttribute = context.SyntaxProvider.ForAttributeWithMetadataName(
42+
"Microsoft.Extensions.Validation.ValidatableTypeAttribute",
43+
predicate: ShouldTransformSymbolWithAttribute,
44+
transform: TransformValidatableTypeWithAttribute
45+
);
46+
47+
// Extract types that have been marked with the embedded [ValidatableType].
48+
var generatedValidatableTypesWithAttribute = context.SyntaxProvider.CreateSyntaxProvider(
49+
predicate: ShouldTransformSymbolWithEmbeddedValidatableTypeAttribute,
50+
transform: (context, cancellation) => context
51+
).Combine(generatorSettings)
52+
.Select((combined, cancellation) =>
53+
{
54+
var (syntaxContext, settings) = combined;
55+
if (!settings.ShouldGenerateAttribute || string.IsNullOrEmpty(settings.RootNamespace))
56+
{
57+
return [];
58+
}
59+
60+
return TransformValidatableTypeWithEmbeddedValidatableTypeAttribute(syntaxContext, settings, cancellation);
61+
})
62+
.Where(t => t.Length > 0);
63+
64+
var allValidatableTypes = generatedValidatableTypesWithAttribute.Collect()
65+
.Combine(validatableTypesWithAttribute.Collect())
66+
.SelectMany((pair, cancellation) => pair.Left.Concat(pair.Right).ToImmutableArray());
67+
4268
// Extract all minimal API endpoints in the application.
4369
var endpoints = context.SyntaxProvider
4470
.CreateSyntaxProvider(
4571
predicate: FindEndpoints,
4672
transform: TransformEndpoints)
4773
.Where(endpoint => endpoint is not null);
74+
4875
// Extract validatable types from all endpoints.
4976
var validatableTypesFromEndpoints = endpoints
5077
.Select(ExtractValidatableEndpoint);
78+
5179
// Join all validatable types encountered in the type graph.
52-
var validatableTypes = validatableTypesWithAttribute
80+
var validatableTypes = allValidatableTypes
5381
.Concat(validatableTypesFromEndpoints)
5482
.Distinct(ValidatableTypeComparer.Instance)
5583
.Collect();
@@ -99,5 +127,5 @@ internal sealed class ValidatableTypeAttribute : global::System.Attribute
99127
context.AddSource("ValidatableTypeAttribute.g.cs", validatableTypeAttributeSource);
100128
}
101129

102-
private readonly record struct GeneratorSettings(string? RootNamespace, bool ShouldGenerateAttribute);
130+
internal readonly record struct GeneratorSettings(string? RootNamespace, bool ShouldGenerateAttribute);
103131
}

0 commit comments

Comments
 (0)