Skip to content

Commit 0837c72

Browse files
committed
DependencyPropertyGenerator using SyntaxFactory
1 parent 370c122 commit 0837c72

6 files changed

Lines changed: 60 additions & 22 deletions

File tree

src/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration/AttributeGenerator.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ public static void GenerateAllAttributes(IncrementalGeneratorPostInitializationC
5757
SyntaxToken identifierOfDependencyPropertyAttribute = Identifier("DependencyPropertyAttribute");
5858
SyntaxToken identifierOfName = Identifier("name");
5959
SyntaxToken identifierOfIsAttached = Identifier("IsAttached");
60+
SyntaxToken identifierOfTargetType = Identifier("TargetType");
6061
SyntaxToken identifierOfDefaultValue = Identifier("DefaultValue");
6162
SyntaxToken identifierOfCreateDefaultValueCallbackName = Identifier("CreateDefaultValueCallbackName");
6263
SyntaxToken identifierOfPropertyChangedCallbackName = Identifier("PropertyChangedCallbackName");
64+
SyntaxToken identifierOfNotNull = Identifier("NotNull");
6365

6466
SyntaxToken identifierOfFieldAccessorAttribute = Identifier("FieldAccessorAttribute");
6567

@@ -128,6 +130,9 @@ public static void GenerateAllAttributes(IncrementalGeneratorPostInitializationC
128130
PropertyDeclaration(BoolType, identifierOfIsAttached)
129131
.WithModifiers(PublicTokenList)
130132
.WithAccessorList(GetAndSetAccessorList),
133+
PropertyDeclaration(TypeOfSystemType, identifierOfTargetType)
134+
.WithModifiers(PublicTokenList)
135+
.WithAccessorList(GetAndSetAccessorList),
131136
PropertyDeclaration(NullableObjectType, identifierOfDefaultValue)
132137
.WithModifiers(PublicTokenList)
133138
.WithAccessorList(GetAndSetAccessorList),
@@ -136,7 +141,10 @@ public static void GenerateAllAttributes(IncrementalGeneratorPostInitializationC
136141
.WithAccessorList(GetAndSetAccessorList),
137142
PropertyDeclaration(NullableStringType, identifierOfPropertyChangedCallbackName)
138143
.WithModifiers(PublicTokenList)
139-
.WithAccessorList(GetAndSetAccessorList)
144+
.WithAccessorList(GetAndSetAccessorList),
145+
PropertyDeclaration(BoolType, identifierOfNotNull)
146+
.WithModifiers(PublicTokenList)
147+
.WithAccessorList(GetAndSetAccessorList),
140148
])),
141149
ClassDeclaration(identifierOfFieldAccessorAttribute)
142150
.WithAttributeLists(SingletonList(SystemAttributeUsageList(AttributeTargetsProperty, inherited: false)))

src/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration/Primitive/FastSyntaxFactory.BinaryExpression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ public static BinaryExpressionSyntax AddExpression(ExpressionSyntax left, Expres
1212
return SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression, left, right);
1313
}
1414

15+
public static BinaryExpressionSyntax AsExpression(ExpressionSyntax left, ExpressionSyntax right)
16+
{
17+
return SyntaxFactory.BinaryExpression(SyntaxKind.AsExpression, left, right);
18+
}
19+
1520
public static BinaryExpressionSyntax BitwiseOrExpression(ExpressionSyntax left, ExpressionSyntax right)
1621
{
1722
return SyntaxFactory.BinaryExpression(SyntaxKind.BitwiseOrExpression, left, right);

src/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration/Primitive/FastSyntaxFactory.TokenList.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ internal static partial class FastSyntaxFactory
3030

3131
public static SyntaxTokenList PrivateStaticExternTokenList { get; } = SyntaxFactory.TokenList(PrivateKeyword, StaticKeyword, ExternKeyword);
3232

33+
public static SyntaxTokenList PrivateStaticReadonlyTokenList { get; } = SyntaxFactory.TokenList(PrivateKeyword, StaticKeyword, ReadOnlyKeyword);
34+
3335
public static SyntaxTokenList ProtectedTokenList { get; } = SyntaxFactory.TokenList(ProtectedKeyword);
3436

3537
public static SyntaxTokenList ProtectedInternalTokenList { get; } = SyntaxFactory.TokenList(ProtectedKeyword, InternalKeyword);

src/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration/Primitive/FastSyntaxFactory.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public static InvocationExpressionSyntax NameOfExpression(ExpressionSyntax argum
7575
return SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("nameof"), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(argument))));
7676
}
7777

78+
79+
7880
public static MemberAccessExpressionSyntax SimpleMemberAccessExpression(ExpressionSyntax expression, SimpleNameSyntax name)
7981
{
8082
return SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, expression, name);

src/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
<PropertyGroup>
4343
<PackageId>Snap.Hutao.SourceGeneration</PackageId>
44-
<Version>1.2.31</Version>
44+
<Version>1.2.32</Version>
4545
<Authors>DGP Studio</Authors>
4646
<IncludeBuildOutput>false</IncludeBuildOutput>
4747
<DevelopmentDependency>true</DevelopmentDependency>

src/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration/Xaml/DependencyPropertyGenerator.cs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,20 @@ private static IEnumerable<MemberDeclarationSyntax> GenerateMembers(DependencyPr
8080
continue;
8181
}
8282

83-
TypeSyntax propertyTypeSyntax = propertyType.GetSyntax();
83+
TypeSyntax propertyTypeSyntaxWithoutNullabilityAnnotation = propertyType.GetSyntax();
84+
TypeSyntax propertyTypeSyntax = propertyTypeSyntaxWithoutNullabilityAnnotation;
85+
86+
if (!attribute.HasNamedArgument("NotNull", true))
87+
{
88+
propertyTypeSyntax = NullableType(propertyTypeSyntax);
89+
}
8490

8591
// Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
8692
// RegisterAttached(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata)
8793
SeparatedSyntaxList<ArgumentSyntax> registerArguments = SeparatedList(
8894
[
89-
Argument(NameOfExpression(IdentifierName(name))), // name
90-
Argument(TypeOfExpression(propertyTypeSyntax)), // propertyType
95+
Argument(StringLiteralExpression(name)), // name
96+
Argument(TypeOfExpression(propertyTypeSyntaxWithoutNullabilityAnnotation)), // propertyType
9197
Argument(TypeOfExpression(IdentifierName(context.Hierarchy.Hierarchy[0].MinimallyQualifiedName))) // ownerType
9298
]);
9399

@@ -97,7 +103,7 @@ private static IEnumerable<MemberDeclarationSyntax> GenerateMembers(DependencyPr
97103
// PropertyMetadata.Create(CreateDefaultValueCallback createDefaultValueCallback, PropertyChangedCallback propertyChangedCallback)
98104

99105
SeparatedSyntaxList<ArgumentSyntax> createArguments = SeparatedList<ArgumentSyntax>();
100-
if (attribute.TryGetNamedArgument("CreateDefaultValueCallback", out string? createDefaultValueCallbackName))
106+
if (attribute.TryGetNamedArgument("CreateDefaultValueCallbackName", out string? createDefaultValueCallbackName))
101107
{
102108
createArguments = createArguments.Add(Argument(IdentifierName(createDefaultValueCallbackName)));
103109
}
@@ -106,10 +112,10 @@ private static IEnumerable<MemberDeclarationSyntax> GenerateMembers(DependencyPr
106112
bool hasDefaultValue = attribute.TryGetNamedArgument("DefaultValue", out TypedConstantInfo? defaultValue);
107113
createArguments = createArguments.Add(hasDefaultValue
108114
? Argument(defaultValue!.GetSyntax())
109-
: Argument(NullLiteralExpression));
115+
: Argument(DefaultExpression(ObjectType)));
110116
}
111117

112-
if (attribute.TryGetNamedArgument("PropertyChangedCallback", out string? propertyChangedCallbackName))
118+
if (attribute.TryGetNamedArgument("PropertyChangedCallbackName", out string? propertyChangedCallbackName))
113119
{
114120
createArguments = createArguments.Add(Argument(IdentifierName(propertyChangedCallbackName)));
115121
}
@@ -135,19 +141,20 @@ private static IEnumerable<MemberDeclarationSyntax> GenerateMembers(DependencyPr
135141
SimpleMemberAccessExpression(
136142
NameOfMicrosoftUIXaml,
137143
IdentifierName("DependencyProperty")),
138-
IdentifierName(isAttached ? "Register" : "RegisterAttached")))
139-
.WithArgumentList(ArgumentList(registerArguments)))))));
144+
IdentifierName(isAttached ? "RegisterAttached" : "Register")))
145+
.WithArgumentList(ArgumentList(registerArguments)))))))
146+
.WithModifiers(PrivateStaticReadonlyTokenList);
140147

141148
if (!isAttached)
142149
{
143150
// Generate a property for non-attached properties
144-
yield return PropertyDeclaration(dependencyPropertyType, Identifier(name))
151+
yield return PropertyDeclaration(propertyTypeSyntax, Identifier(name))
145152
.WithModifiers(PublicTokenList)
146153
.WithIdentifier(Identifier(name))
147154
.WithAccessorList(AccessorList(List(
148155
[
149156
GetAccessorDeclaration().WithExpressionBody(ArrowExpressionClause(CastExpression(
150-
propertyTypeSyntax,
157+
propertyTypeSyntaxWithoutNullabilityAnnotation,
151158
InvocationExpression(IdentifierName("GetValue"))
152159
.WithArgumentList(ArgumentList(SingletonSeparatedList(
153160
Argument(IdentifierName(propertyName)))))))),
@@ -162,35 +169,49 @@ private static IEnumerable<MemberDeclarationSyntax> GenerateMembers(DependencyPr
162169
}
163170
else
164171
{
172+
TypeSyntax targetTypeSyntax;
173+
if (attribute.TryGetNamedArgument("TargetType", out TypedConstantInfo? targetType) &&
174+
targetType is TypedConstantInfo.Type type)
175+
{
176+
targetTypeSyntax = NullableType(ParseName(type.FullyQualifiedTypeName));
177+
}
178+
else
179+
{
180+
targetTypeSyntax = NullableType(QualifiedName(NameOfMicrosoftUIXaml, IdentifierName("DependencyObject")));
181+
}
182+
165183
// Generate static methods for attached properties
166184
yield return MethodDeclaration(propertyTypeSyntax, Identifier($"Get{name}"))
167185
.WithModifiers(PublicStaticTokenList)
168186
.WithParameterList(ParameterList(SeparatedList(
169187
[
170-
Parameter(NullableType(QualifiedName(NameOfMicrosoftUIXaml, IdentifierName("DependencyObject"))), Identifier("obj"))
188+
Parameter(targetTypeSyntax, Identifier("obj"))
171189
])))
172190
.WithBody(Block(SingletonList(
173-
ReturnStatement(CastExpression(propertyTypeSyntax,
174-
InvocationExpression(IdentifierName("GetValue"))
175-
.WithArgumentList(ArgumentList(SingletonSeparatedList(
176-
Argument(IdentifierName(propertyName))))))))));
191+
ReturnStatement(CastExpression(
192+
propertyTypeSyntax,
193+
ConditionalAccessExpression(
194+
IdentifierName("obj"),
195+
InvocationExpression(MemberBindingExpression(IdentifierName("GetValue")))
196+
.WithArgumentList(ArgumentList(SingletonSeparatedList(
197+
Argument(IdentifierName(propertyName)))))))))));
177198

178199
yield return MethodDeclaration(VoidType, Identifier($"Set{name}"))
179200
.WithModifiers(PublicStaticTokenList)
180201
.WithParameterList(ParameterList(SeparatedList(
181202
[
182-
Parameter(NullableType(QualifiedName(NameOfMicrosoftUIXaml, IdentifierName("DependencyObject"))), Identifier("obj")),
203+
Parameter(targetTypeSyntax, Identifier("obj")),
183204
Parameter(propertyTypeSyntax, Identifier("value"))
184205
])))
185206
.WithBody(Block(SingletonList(
186-
ExpressionStatement(InvocationExpression(SimpleMemberAccessExpression(
207+
ExpressionStatement(ConditionalAccessExpression(
187208
IdentifierName("obj"),
188-
IdentifierName("SetValue")))
189-
.WithArgumentList(ArgumentList(SeparatedList(
209+
InvocationExpression(MemberBindingExpression(IdentifierName("SetValue")))
210+
.WithArgumentList(ArgumentList(SeparatedList(
190211
[
191212
Argument(IdentifierName(propertyName)),
192213
Argument(IdentifierName("value"))
193-
])))))));
214+
]))))))));
194215
}
195216
}
196217
}

0 commit comments

Comments
 (0)