1
1
using System . Text ;
2
2
using Microsoft . CodeAnalysis ;
3
+ using Microsoft . CodeAnalysis . CSharp ;
3
4
using Microsoft . CodeAnalysis . CSharp . Syntax ;
5
+ using Microsoft . CodeAnalysis . Text ;
4
6
using UnityUxmlGenerator . Captures ;
5
7
using UnityUxmlGenerator . Extensions ;
6
8
7
9
namespace UnityUxmlGenerator ;
8
10
9
11
internal sealed partial class UxmlGenerator
10
12
{
11
- private static string GenerateUxmlTraits ( GeneratorExecutionContext context , UxmlTraitsCapture capture )
13
+ private static SourceText GenerateUxmlTraits ( GeneratorExecutionContext context , UxmlTraitsCapture capture )
12
14
{
13
- return $$ """
14
- // <auto-generated/>
15
- #pragma warning disable
15
+ var @class = ClassDeclaration ( capture . ClassName ) . AddModifiers ( Token ( SyntaxKind . PartialKeyword ) ) ;
16
16
17
- #nullable enable
17
+ var traitsClass = GetTraitsClass ( context , capture ) ;
18
18
19
- namespace {{ capture . ClassNamespace }}
20
- {
21
- partial class {{ capture . ClassName }}
19
+ return GetCompilationUnit ( @class , capture . ClassNamespace , traitsClass ) . GetText ( Encoding . UTF8 ) ;
20
+ }
21
+
22
+ private static MemberDeclarationSyntax GetTraitsClass ( GeneratorExecutionContext context , UxmlTraitsCapture capture )
22
23
{
23
- {{ GeneratedCodeAttribute }}
24
- public new class UxmlTraits : {{ GetBaseClassName ( context , capture ) }} .UxmlTraits
25
- {
26
- {{ GetUxmlTraitsFields ( capture . Properties ) }}
24
+ var uxmlTraitsBaseList = SimpleBaseType ( IdentifierName ( $ "{ GetBaseClassName ( context , capture ) } .UxmlTraits") ) ;
27
25
28
- {{ GetUxmlTraitsInitialization ( capture . ClassName , capture . Properties ) }}
29
- }
30
- }
31
- }
32
- """ ;
26
+ return
27
+ ClassDeclaration ( "UxmlTraits" )
28
+ . WithModifiers ( TokenList ( Token ( SyntaxKind . PublicKeyword ) , Token ( SyntaxKind . NewKeyword ) ) )
29
+ . WithBaseList ( BaseList ( SingletonSeparatedList < BaseTypeSyntax > ( uxmlTraitsBaseList ) ) )
30
+ . WithMembers ( List ( GetTraitsClassMembers ( capture ) ) ) ;
33
31
}
34
32
35
33
private static string GetBaseClassName ( GeneratorExecutionContext context , UxmlTraitsCapture capture )
@@ -58,52 +56,125 @@ private static string GetBaseClassName(GeneratorExecutionContext context, UxmlTr
58
56
return string . Empty ;
59
57
}
60
58
61
- private static string GetUxmlTraitsFields ( List < ( string , string ? ) > properties )
59
+ private static IEnumerable < MemberDeclarationSyntax > GetTraitsClassMembers ( UxmlTraitsCapture capture )
62
60
{
63
- var stringBuilder = new StringBuilder ( ) ;
61
+ var members = new List < MemberDeclarationSyntax > ( GetAttributeFields ( capture ) ) ;
64
62
65
- foreach ( var ( propertyName , uxmlAttributeDefaultValue ) in properties )
63
+ var initMethodBody = new List < StatementSyntax >
66
64
{
65
+ ExpressionStatement (
66
+ InvocationExpression ( MemberAccessExpression ( SyntaxKind . SimpleMemberAccessExpression , BaseExpression ( ) ,
67
+ IdentifierName ( "Init" ) ) )
68
+ . WithArgumentList ( ArgumentList ( SeparatedList < ArgumentSyntax > ( new SyntaxNodeOrToken [ ]
69
+ {
70
+ Argument ( IdentifierName ( "visualElement" ) ) ,
71
+ Token ( SyntaxKind . CommaToken ) ,
72
+ Argument ( IdentifierName ( "bag" ) ) ,
73
+ Token ( SyntaxKind . CommaToken ) ,
74
+ Argument ( IdentifierName ( "context" ) )
75
+ } ) ) ) ) ,
76
+ LocalDeclarationStatement (
77
+ VariableDeclaration ( IdentifierName ( Identifier ( TriviaList ( ) , SyntaxKind . VarKeyword , "var" , "var" , TriviaList ( ) ) ) )
78
+ . WithVariables ( SingletonSeparatedList (
79
+ VariableDeclarator ( Identifier ( "control" ) )
80
+ . WithInitializer ( EqualsValueClause ( CastExpression ( IdentifierName ( capture . ClassName ) , IdentifierName ( "visualElement" ) ) ) ) ) ) )
81
+ } ;
82
+
83
+ initMethodBody . AddRange ( GetAttributeValueAssignments ( capture ) ) ;
84
+
85
+ var initMethod =
86
+ MethodDeclaration ( PredefinedType ( Token ( SyntaxKind . VoidKeyword ) ) , Identifier ( "Init" ) )
87
+ . WithModifiers ( TokenList ( Token ( SyntaxKind . PublicKeyword ) , Token ( SyntaxKind . OverrideKeyword ) ) )
88
+ . WithParameterList ( ParameterList ( SeparatedList < ParameterSyntax > ( new SyntaxNodeOrToken [ ]
89
+ {
90
+ Parameter ( Identifier ( "visualElement" ) )
91
+ . WithType ( IdentifierName ( "global::UnityEngine.UIElements.VisualElement" ) ) ,
92
+ Token ( SyntaxKind . CommaToken ) ,
93
+ Parameter ( Identifier ( "bag" ) )
94
+ . WithType ( IdentifierName ( "global::UnityEngine.UIElements.IUxmlAttributes" ) ) ,
95
+ Token ( SyntaxKind . CommaToken ) ,
96
+ Parameter ( Identifier ( "context" ) )
97
+ . WithType ( IdentifierName ( "global::UnityEngine.UIElements.CreationContext" ) )
98
+ } ) ) )
99
+ . WithBody ( Block ( initMethodBody ) ) ;
100
+
101
+ members . Add ( initMethod ) ;
102
+
103
+ return ProcessMemberDeclarations ( members ) ;
104
+ }
105
+
106
+ private static IEnumerable < MemberDeclarationSyntax > GetAttributeFields ( UxmlTraitsCapture capture )
107
+ {
108
+ var fields = new List < MemberDeclarationSyntax > ( ) ;
109
+
110
+ foreach ( var ( property , uxmlAttributeDefaultValue ) in capture . Properties )
111
+ {
112
+ var propertyName = property . GetName ( ) ;
113
+
114
+ var fieldName = propertyName . ToPrivateFieldName ( ) ;
115
+
116
+ var attributeType = "UxmlStringAttributeDescription" ;
67
117
var attributeUxmlName = propertyName . ToDashCase ( ) ;
68
- var attributeFieldName = propertyName . ToPrivateFieldName ( ) ;
69
118
var attributeDefaultValue = uxmlAttributeDefaultValue ?? string . Empty ;
70
119
71
- stringBuilder . AppendLine ( $ "\t \t \t { GeneratedCodeAttribute } ") ;
72
- stringBuilder . AppendLine ( $$ """
73
- private readonly global::UnityEngine.UIElements.UxmlStringAttributeDescription {{ attributeFieldName }} = new()
74
- { name = "{{ attributeUxmlName }} ", defaultValue = "{{ attributeDefaultValue }} " };
75
- """ ) ;
76
- stringBuilder . AppendLine ( ) ;
120
+ fields . Add ( GetAttributeFieldDeclaration ( attributeType , fieldName , attributeUxmlName ,
121
+ attributeDefaultValue ) ) ;
77
122
}
78
123
79
- return stringBuilder . ToString ( ) . Trim ( ) ;
124
+ return fields ;
80
125
}
81
126
82
- private static string GetUxmlTraitsInitialization ( string elementClassName ,
83
- List < ( string , string ? ) > properties )
127
+ private static FieldDeclarationSyntax GetAttributeFieldDeclaration ( string attributeType , string fieldName ,
128
+ string attributeName , string attributeDefaultValue )
84
129
{
85
- var stringBuilder = new StringBuilder ( ) ;
130
+ return
131
+ FieldDeclaration ( VariableDeclaration ( IdentifierName ( $ "global::UnityEngine.UIElements.{ attributeType } ") )
132
+ . WithVariables ( SingletonSeparatedList ( VariableDeclarator ( Identifier ( fieldName ) )
133
+ . WithInitializer ( EqualsValueClause ( ImplicitObjectCreationExpression ( )
134
+ . WithInitializer ( InitializerExpression ( SyntaxKind . ObjectInitializerExpression ,
135
+ SeparatedList < ExpressionSyntax > ( new SyntaxNodeOrToken [ ]
136
+ {
137
+ AssignmentExpression ( SyntaxKind . SimpleAssignmentExpression ,
138
+ IdentifierName ( "name" ) ,
139
+ LiteralExpression ( SyntaxKind . StringLiteralExpression , Literal ( attributeName ) ) ) ,
140
+ Token ( SyntaxKind . CommaToken ) ,
141
+ AssignmentExpression ( SyntaxKind . SimpleAssignmentExpression ,
142
+ IdentifierName ( "defaultValue" ) ,
143
+ LiteralExpression ( SyntaxKind . StringLiteralExpression , Literal ( attributeDefaultValue ) ) )
144
+ } ) ) ) ) ) ) ) )
145
+ . WithModifiers ( TokenList ( Token ( SyntaxKind . PrivateKeyword ) , Token ( SyntaxKind . ReadOnlyKeyword ) ) ) ;
146
+ }
86
147
87
- foreach ( var ( propertyName , _) in properties )
148
+ private static IEnumerable < StatementSyntax > GetAttributeValueAssignments ( UxmlTraitsCapture capture )
149
+ {
150
+ var attributeValueAssignments = new List < StatementSyntax > ( ) ;
151
+
152
+ foreach ( var ( property , _) in capture . Properties )
88
153
{
89
- var attributeFieldName = propertyName . ToPrivateFieldName ( ) ;
154
+ var propertyName = property . GetName ( ) ;
155
+ var fieldName = propertyName . ToPrivateFieldName ( ) ;
90
156
91
- stringBuilder . AppendLine (
92
- $ "\t \t \t \t control.{ propertyName } = { attributeFieldName } .GetValueFromBag(bag, context);") ;
157
+ attributeValueAssignments . Add ( GetAttributeValueAssignment ( propertyName , fieldName ) ) ;
93
158
}
94
159
95
- return $$ """
96
- {{ GeneratedCodeAttribute }}
97
- [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
98
- public override void Init(global::UnityEngine.UIElements.VisualElement visualElement,
99
- global::UnityEngine.UIElements.IUxmlAttributes bag,
100
- global::UnityEngine.UIElements.CreationContext context)
101
- {
102
- base.Init(visualElement, bag, context);
103
-
104
- var control = ({{ elementClassName }} ) visualElement;
105
- {{ stringBuilder . ToString ( ) . Trim ( ) }}
106
- }
107
- """ . Trim ( ) ;
160
+ return attributeValueAssignments ;
161
+ }
162
+
163
+ private static StatementSyntax GetAttributeValueAssignment ( string propertyName , string fieldName )
164
+ {
165
+ return
166
+ ExpressionStatement (
167
+ AssignmentExpression ( SyntaxKind . SimpleAssignmentExpression ,
168
+ MemberAccessExpression ( SyntaxKind . SimpleMemberAccessExpression , IdentifierName ( "control" ) ,
169
+ IdentifierName ( propertyName ) ) ,
170
+ InvocationExpression ( MemberAccessExpression ( SyntaxKind . SimpleMemberAccessExpression ,
171
+ IdentifierName ( fieldName ) , IdentifierName ( "GetValueFromBag" ) ) )
172
+ . WithArgumentList ( ArgumentList ( SeparatedList < ArgumentSyntax > (
173
+ new SyntaxNodeOrToken [ ]
174
+ {
175
+ Argument ( IdentifierName ( "bag" ) ) ,
176
+ Token ( SyntaxKind . CommaToken ) ,
177
+ Argument ( IdentifierName ( "context" ) )
178
+ } ) ) ) ) ) ;
108
179
}
109
180
}
0 commit comments