Skip to content

Commit 36b0c25

Browse files
authored
Merge pull request #879 from Sergio0694/dev/minor-tweaks
Minor [CanvasEffectProperty] generator tweaks
2 parents 0fbe1a6 + e80b110 commit 36b0c25

File tree

5 files changed

+109
-8
lines changed

5 files changed

+109
-8
lines changed

src/ComputeSharp.D2D1.UI.SourceGenerators/CanvasEffectPropertyGenerator.Execute.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ public static bool IsCandidatePropertyDeclaration(SyntaxNode node, CancellationT
4646
return false;
4747
}
4848

49+
// Static properties are not supported
50+
if (property.Modifiers.Any(SyntaxKind.StaticKeyword))
51+
{
52+
return false;
53+
}
54+
4955
// The accessors must be a get and a set (with any accessibility)
5056
if (accessors[0].Kind() is not (SyntaxKind.GetAccessorDeclaration or SyntaxKind.SetAccessorDeclaration) ||
5157
accessors[1].Kind() is not (SyntaxKind.GetAccessorDeclaration or SyntaxKind.SetAccessorDeclaration))
@@ -128,6 +134,11 @@ public static CanvasEffectInvalidationType GetCanvasEffectInvalidationType(Attri
128134
return CanvasEffectInvalidationType.Update;
129135
}
130136

137+
/// <summary>
138+
/// Writes all implementations of partial effect property declarations.
139+
/// </summary>
140+
/// <param name="properties">The input set of declared effect properties.</param>
141+
/// <param name="writer">The <see cref="IndentedTextWriter"/> instance to write into.</param>
131142
public static void WritePropertyDeclarations(EquatableArray<CanvasEffectPropertyInfo> properties, IndentedTextWriter writer)
132143
{
133144
// Helper to get the nullable type name for the initial property value
@@ -163,8 +174,10 @@ static string GetExpressionWithTrailingSpace(Accessibility accessibility)
163174

164175
writer.WriteLine("/// <inheritdoc/>");
165176
writer.WriteGeneratedAttributes(GeneratorName);
166-
writer.WriteLine($$"""
167-
{{GetExpressionWithTrailingSpace(propertyInfo.DeclaredAccessibility)}}partial {{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}}
177+
writer.Write(GetExpressionWithTrailingSpace(propertyInfo.DeclaredAccessibility));
178+
writer.WriteIf(propertyInfo.IsRequired, "required ");
179+
writer.WriteLine($"partial {propertyInfo.TypeNameWithNullabilityAnnotations} {propertyInfo.PropertyName}");
180+
writer.WriteLine($$"""
168181
{
169182
{{GetExpressionWithTrailingSpace(propertyInfo.GetterAccessibility)}}get => field;
170183
{{GetExpressionWithTrailingSpace(propertyInfo.SetterAccessibility)}}set

src/ComputeSharp.D2D1.UI.SourceGenerators/CanvasEffectPropertyGenerator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
6363
}
6464

6565
// Also ignore all properties that have an invalid declaration
66-
if (propertySymbol.IsStatic || propertySymbol.ReturnsByRef || propertySymbol.ReturnsByRefReadonly || propertySymbol.Type.IsRefLikeType)
66+
if (propertySymbol.ReturnsByRef || propertySymbol.ReturnsByRefReadonly || propertySymbol.Type.IsRefLikeType)
6767
{
6868
return default;
6969
}
@@ -101,6 +101,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
101101
// This will cover both reference types as well T when the constraints are not struct or unmanaged.
102102
// If this is true, it means the field storage can potentially be in a null state (even if not annotated).
103103
bool isReferenceTypeOrUnconstraindTypeParameter = !propertySymbol.Type.IsValueType;
104+
bool isRequired = propertySymbol.IsRequired;
104105

105106
// Finally, get the hierarchy too
106107
HierarchyInfo hierarchyInfo = HierarchyInfo.From(typeSymbol);
@@ -115,6 +116,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
115116
SetterAccessibility: setterAccessibility,
116117
TypeNameWithNullabilityAnnotations: typeNameWithNullabilityAnnotations,
117118
IsReferenceTypeOrUnconstraindTypeParameter: isReferenceTypeOrUnconstraindTypeParameter,
119+
IsRequired: isRequired,
118120
InvalidationType: invalidationType);
119121
})
120122
.WithTrackingName(WellKnownTrackingNames.Execute)

src/ComputeSharp.D2D1.UI.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ internal static class DiagnosticDescriptors
8080
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp");
8181

8282
/// <summary>
83-
/// Gets a <see cref="DiagnosticDescriptor"/> for a CanvasEffect property with invalid accessors.
83+
/// Gets a <see cref="DiagnosticDescriptor"/> for a CanvasEffect property that is not an incomplete partial property definition.
8484
/// <para>
8585
/// Format: <c>"The property "{0}" is not an incomplete partial definition ([GeneratedCanvasEffectProperty] must be used on partial property definitions with no implementation part)"</c>.
8686
/// </para>
@@ -92,11 +92,11 @@ internal static class DiagnosticDescriptors
9292
category: DiagnosticCategory,
9393
defaultSeverity: DiagnosticSeverity.Error,
9494
isEnabledByDefault: true,
95-
description: "A property using [GeneratedCanvasEffectProperty] is either not partial, or a partial implementation part ([GeneratedCanvasEffectProperty] must be used on partial property definitions with no implementation par).",
95+
description: "A property using [GeneratedCanvasEffectProperty] is either not partial, or a partial implementation part ([GeneratedCanvasEffectProperty] must be used on partial property definitions with no implementation part).",
9696
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp");
9797

9898
/// <summary>
99-
/// Gets a <see cref="DiagnosticDescriptor"/> for a CanvasEffect property with invalid accessors.
99+
/// Gets a <see cref="DiagnosticDescriptor"/> for a CanvasEffect property that returns a ref value.
100100
/// <para>
101101
/// Format: <c>"The property "{0}" returns a value by reference ([GeneratedCanvasEffectProperty] must be used on properties returning a type by value)"</c>.
102102
/// </para>
@@ -112,7 +112,7 @@ internal static class DiagnosticDescriptors
112112
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp");
113113

114114
/// <summary>
115-
/// Gets a <see cref="DiagnosticDescriptor"/> for a CanvasEffect property with invalid accessors.
115+
/// Gets a <see cref="DiagnosticDescriptor"/> for a CanvasEffect property that returns a byref-like value.
116116
/// <para>
117117
/// Format: <c>"The property "{0}" returns a ref struct value ([GeneratedCanvasEffectProperty] must be used on properties with a type that is not a ref struct)"</c>.
118118
/// </para>
@@ -128,7 +128,7 @@ internal static class DiagnosticDescriptors
128128
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp");
129129

130130
/// <summary>
131-
/// Gets a <see cref="DiagnosticDescriptor"/> for a CanvasEffect property with invalid accessors.
131+
/// Gets a <see cref="DiagnosticDescriptor"/> for when C# is not set to 'preview'.
132132
/// <para>
133133
/// Format: <c>"Using [GeneratedCanvasEffectProperty] requires the C# language version to be set to 'preview', as support for the 'field' keyword is needed by the source generators to emit valid code (add &lt;LangVersion&gt;preview&lt;/LangVersion&gt; to your .csproj/.props file)"</c>.
134134
/// </para>

src/ComputeSharp.D2D1.UI.SourceGenerators/Models/CanvasEffectPropertyInfo.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace ComputeSharp.D2D1.WinUI.SourceGenerators.Models;
1717
/// <param name="SetterAccessibility">The accessibility of the <see langword="set"/> accessor, if available.</param>
1818
/// <param name="TypeNameWithNullabilityAnnotations">The type name for the generated property, including nullability annotations.</param>
1919
/// <param name="IsReferenceTypeOrUnconstraindTypeParameter">Indicates whether the property is of a reference type or an unconstrained type parameter.</param>
20+
/// <param name="IsRequired">Whether or not the generated property should be marked as required.</param>
2021
/// <param name="InvalidationType">The invalidation type to request.</param>
2122
internal sealed record CanvasEffectPropertyInfo(
2223
HierarchyInfo Hierarchy,
@@ -26,4 +27,5 @@ internal sealed record CanvasEffectPropertyInfo(
2627
Accessibility SetterAccessibility,
2728
string TypeNameWithNullabilityAnnotations,
2829
bool IsReferenceTypeOrUnconstraindTypeParameter,
30+
bool IsRequired,
2931
CanvasEffectInvalidationType InvalidationType);

tests/ComputeSharp.D2D1.WinUI.Tests.SourceGenerators/Test_CanvasEffectPropertyGenerator.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,90 @@ private set
344344
VerifyGeneratedDiagnostics(source, ("MyNamespace.MyEffect.g.cs", result));
345345
}
346346

347+
[TestMethod]
348+
public void SingleProperty_Required()
349+
{
350+
const string source = """
351+
using ComputeSharp.D2D1.WinUI;
352+
353+
namespace MyNamespace;
354+
355+
public abstract partial class MyEffect : CanvasEffect
356+
{
357+
[GeneratedCanvasEffectProperty]
358+
public required partial int Number { get; set; }
359+
}
360+
""";
361+
362+
const string result = """"
363+
// <auto-generated/>
364+
#pragma warning disable
365+
366+
namespace MyNamespace
367+
{
368+
/// <inheritdoc cref="MyEffect"/>
369+
partial class MyEffect
370+
{
371+
/// <inheritdoc/>
372+
[global::System.CodeDom.Compiler.GeneratedCode("ComputeSharp.D2D1.WinUI.CanvasEffectPropertyGenerator", <ASSEMBLY_VERSION>)]
373+
[global::System.Diagnostics.DebuggerNonUserCode]
374+
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
375+
public required partial int Number
376+
{
377+
get => field;
378+
set
379+
{
380+
if (global::System.Collections.Generic.EqualityComparer<int>.Default.Equals(field, value))
381+
{
382+
return;
383+
}
384+
385+
int oldValue = field;
386+
387+
OnNumberChanging(value);
388+
OnNumberChanging(oldValue, value);
389+
390+
field = value;
391+
392+
OnNumberChanged(value);
393+
OnNumberChanged(oldValue, value);
394+
395+
InvalidateEffectGraph(global::ComputeSharp.D2D1.WinUI.CanvasEffectInvalidationType.Update);
396+
}
397+
}
398+
399+
/// <summary>Executes the logic for when <see cref="Number"/> is changing.</summary>
400+
/// <param name="value">The new property value being set.</param>
401+
/// <remarks>This method is invoked right before the value of <see cref="Number"/> is changed.</remarks>
402+
[global::System.CodeDom.Compiler.GeneratedCode("ComputeSharp.D2D1.WinUI.CanvasEffectPropertyGenerator", <ASSEMBLY_VERSION>)]
403+
partial void OnNumberChanging(int newValue);
404+
405+
/// <summary>Executes the logic for when <see cref="Number"/> is changing.</summary>
406+
/// <param name="oldValue">The previous property value that is being replaced.</param>
407+
/// <param name="newValue">The new property value being set.</param>
408+
/// <remarks>This method is invoked right before the value of <see cref="Number"/> is changed.</remarks>
409+
[global::System.CodeDom.Compiler.GeneratedCode("ComputeSharp.D2D1.WinUI.CanvasEffectPropertyGenerator", <ASSEMBLY_VERSION>)]
410+
partial void OnNumberChanging(int oldValue, int newValue);
411+
412+
/// <summary>Executes the logic for when <see cref="Number"/> has just changed.</summary>
413+
/// <param name="value">The new property value that has been set.</param>
414+
/// <remarks>This method is invoked right after the value of <see cref="Number"/> is changed.</remarks>
415+
[global::System.CodeDom.Compiler.GeneratedCode("ComputeSharp.D2D1.WinUI.CanvasEffectPropertyGenerator", <ASSEMBLY_VERSION>)]
416+
partial void OnNumberChanged(int newValue);
417+
418+
/// <summary>Executes the logic for when <see cref="Number"/> has just changed.</summary>
419+
/// <param name="oldValue">The previous property value that has been replaced.</param>
420+
/// <param name="newValue">The new property value that has been set.</param>
421+
/// <remarks>This method is invoked right after the value of <see cref="Number"/> is changed.</remarks>
422+
[global::System.CodeDom.Compiler.GeneratedCode("ComputeSharp.D2D1.WinUI.CanvasEffectPropertyGenerator", <ASSEMBLY_VERSION>)]
423+
partial void OnNumberChanged(int oldValue, int newValue);
424+
}
425+
}
426+
"""";
427+
428+
VerifyGeneratedDiagnostics(source, ("MyNamespace.MyEffect.g.cs", result));
429+
}
430+
347431
[TestMethod]
348432
public void MultipleProperties()
349433
{

0 commit comments

Comments
 (0)