Skip to content

Commit 2dd8ce7

Browse files
committed
Fix #9. Add AttributeUsage attribute.
1 parent 003cf1c commit 2dd8ce7

File tree

2 files changed

+158
-32
lines changed

2 files changed

+158
-32
lines changed

src/UnityUxmlGenerator/UxmlGenerator.Attributes.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,23 @@ internal sealed partial class UxmlGenerator
99
{
1010
private const string AttributeBaseType = "global::System.Attribute";
1111

12+
private const string AttributeClassTarget = "Class";
13+
private const string AttributePropertyTarget = "Property";
14+
1215
private const string UxmlElementClassName = "UxmlElementAttribute";
1316
private const string UxmlAttributeClassName = "UxmlAttributeAttribute";
1417

1518
private static SourceText GenerateUxmlElementAttribute()
1619
{
17-
return GenerateAttributeClass(UxmlElementClassName);
20+
return GenerateAttributeClass(UxmlElementClassName, AttributeClassTarget);
1821
}
1922

2023
private static SourceText GenerateUxmlAttributeAttribute()
2124
{
22-
return GenerateAttributeClass(UxmlAttributeClassName, GetUxmlAttributeMembers());
25+
return GenerateAttributeClass(UxmlAttributeClassName, AttributePropertyTarget, GetUxmlAttributeMembers());
2326
}
2427

25-
private static SourceText GenerateAttributeClass(string attributeClassIdentifier,
28+
private static SourceText GenerateAttributeClass(string attributeClassIdentifier, string attributeTarget,
2629
IEnumerable<MemberDeclarationSyntax>? members = null)
2730
{
2831
return CompilationUnitWidget(
@@ -31,6 +34,20 @@ private static SourceText GenerateAttributeClass(string attributeClassIdentifier
3134
identifier: attributeClassIdentifier,
3235
modifiers: new[] { SyntaxKind.InternalKeyword, SyntaxKind.SealedKeyword },
3336
baseType: SimpleBaseType(IdentifierName(AttributeBaseType)),
37+
attribute: AttributeWidget(
38+
identifier: "global::System.AttributeUsage",
39+
arguments: new[]
40+
{
41+
AttributeArgument(MemberAccessWidget(
42+
identifier: "global::System.AttributeTargets",
43+
memberName: attributeTarget)),
44+
AttributeArgument(AssignmentWidget(
45+
left: IdentifierName("AllowMultiple"),
46+
right: LiteralExpression(SyntaxKind.FalseLiteralExpression))),
47+
AttributeArgument(AssignmentWidget(
48+
left: IdentifierName("Inherited"),
49+
right: LiteralExpression(SyntaxKind.FalseLiteralExpression)))
50+
}),
3451
members: members,
3552
addGeneratedCodeAttributes: true),
3653
normalizeWhitespace: true)

src/UnityUxmlGenerator/UxmlGenerator.Widgets.cs

Lines changed: 138 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ private static CompilationUnitSyntax CompilationUnitWidget(
3535

3636
if (addGeneratedCodeLeadingTrivia)
3737
{
38-
compilationUnit = GeneratedCodeLeadingTrivia(compilationUnit);
38+
compilationUnit = AddGeneratedCodeLeadingTrivia(compilationUnit);
3939
}
4040

4141
return normalizeWhitespace
@@ -71,6 +71,8 @@ private static ClassDeclarationSyntax ClassWidget(
7171
IEnumerable<BaseTypeSyntax>? baseTypes = null,
7272
MemberDeclarationSyntax? member = null,
7373
IEnumerable<MemberDeclarationSyntax>? members = null,
74+
AttributeSyntax? attribute = null,
75+
IEnumerable<AttributeSyntax>? attributes = null,
7476
bool addGeneratedCodeAttributes = false)
7577
{
7678
var classDeclaration = ClassDeclaration(identifier);
@@ -95,7 +97,13 @@ private static ClassDeclarationSyntax ClassWidget(
9597
classDeclaration = classDeclaration.WithMembers(List(members));
9698
}
9799

98-
return BaseWidgetDecoration(classDeclaration, modifier, modifiers, addGeneratedCodeAttributes);
100+
return BaseWidgetDecoration(
101+
widget: classDeclaration,
102+
modifier: modifier,
103+
modifiers: modifiers,
104+
attribute: attribute,
105+
attributes: attributes,
106+
addGeneratedCodeAttributes: addGeneratedCodeAttributes);
99107
}
100108

101109
private static ConstructorDeclarationSyntax ConstructorWidget(
@@ -106,6 +114,8 @@ private static ConstructorDeclarationSyntax ConstructorWidget(
106114
IEnumerable<ParameterSyntax>? parameters = null,
107115
StatementSyntax? bodyStatement = null,
108116
IEnumerable<StatementSyntax>? bodyStatements = null,
117+
AttributeSyntax? attribute = null,
118+
IEnumerable<AttributeSyntax>? attributes = null,
109119
bool addGeneratedCodeAttributes = false)
110120
{
111121
var constructorDeclaration = ConstructorDeclaration(Identifier(identifier));
@@ -132,7 +142,13 @@ private static ConstructorDeclarationSyntax ConstructorWidget(
132142
constructorDeclaration = constructorDeclaration.WithBody(Block(bodyStatements));
133143
}
134144

135-
return BaseWidgetDecoration(constructorDeclaration, modifier, modifiers, addGeneratedCodeAttributes);
145+
return BaseWidgetDecoration(
146+
widget: constructorDeclaration,
147+
modifier: modifier,
148+
modifiers: modifiers,
149+
attribute: attribute,
150+
attributes: attributes,
151+
addGeneratedCodeAttributes: addGeneratedCodeAttributes);
136152
}
137153

138154
private static FieldDeclarationSyntax FieldWidget(
@@ -142,6 +158,8 @@ private static FieldDeclarationSyntax FieldWidget(
142158
IEnumerable<SyntaxKind>? modifiers = null,
143159
ExpressionSyntax? initializer = null,
144160
IEnumerable<ExpressionSyntax>? initializers = null,
161+
AttributeSyntax? attribute = null,
162+
IEnumerable<AttributeSyntax>? attributes = null,
145163
bool addGeneratedCodeAttributes = false)
146164
{
147165
var variableDeclaration = VariableDeclarator(Identifier(identifier));
@@ -161,7 +179,13 @@ private static FieldDeclarationSyntax FieldWidget(
161179
var fieldDeclaration = FieldDeclaration(VariableDeclaration(type)
162180
.WithVariables(SingletonSeparatedList(variableDeclaration)));
163181

164-
return BaseWidgetDecoration(fieldDeclaration, modifier, modifiers, addGeneratedCodeAttributes);
182+
return BaseWidgetDecoration(
183+
widget: fieldDeclaration,
184+
modifier: modifier,
185+
modifiers: modifiers,
186+
attribute: attribute,
187+
attributes: attributes,
188+
addGeneratedCodeAttributes: addGeneratedCodeAttributes);
165189
}
166190

167191
private static PropertyDeclarationSyntax PropertyWidget(
@@ -171,6 +195,9 @@ private static PropertyDeclarationSyntax PropertyWidget(
171195
IEnumerable<SyntaxKind>? modifiers = null,
172196
SyntaxKind? accessor = null,
173197
IEnumerable<SyntaxKind>? accessors = null,
198+
ExpressionSyntax? initializer = null,
199+
AttributeSyntax? attribute = null,
200+
IEnumerable<AttributeSyntax>? attributes = null,
174201
bool addGeneratedCodeAttributes = false)
175202
{
176203
var propertyDeclaration = PropertyDeclaration(type, Identifier(identifier));
@@ -191,7 +218,20 @@ private static PropertyDeclarationSyntax PropertyWidget(
191218
.WithAccessors(accessorList.Accessors.AddRange(accessors.Select(AccessorWidget))));
192219
}
193220

194-
return BaseWidgetDecoration(propertyDeclaration, modifier, modifiers, addGeneratedCodeAttributes);
221+
if (initializer is not null)
222+
{
223+
propertyDeclaration = propertyDeclaration
224+
.WithInitializer(EqualsValueClause(initializer))
225+
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
226+
}
227+
228+
return BaseWidgetDecoration(
229+
widget: propertyDeclaration,
230+
modifier: modifier,
231+
modifiers: modifiers,
232+
attribute: attribute,
233+
attributes: attributes,
234+
addGeneratedCodeAttributes: addGeneratedCodeAttributes);
195235
}
196236

197237
private static MethodDeclarationSyntax MethodWidget(
@@ -203,6 +243,8 @@ private static MethodDeclarationSyntax MethodWidget(
203243
IEnumerable<ParameterSyntax>? parameters = null,
204244
StatementSyntax? bodyStatement = null,
205245
IEnumerable<StatementSyntax>? bodyStatements = null,
246+
AttributeSyntax? attribute = null,
247+
IEnumerable<AttributeSyntax>? attributes = null,
206248
bool addGeneratedCodeAttributes = false)
207249
{
208250
var methodDeclaration = MethodDeclaration(type, Identifier(identifier));
@@ -229,7 +271,13 @@ private static MethodDeclarationSyntax MethodWidget(
229271
methodDeclaration = methodDeclaration.WithBody(Block(bodyStatements));
230272
}
231273

232-
return BaseWidgetDecoration(methodDeclaration, modifier, modifiers, addGeneratedCodeAttributes);
274+
return BaseWidgetDecoration(
275+
widget: methodDeclaration,
276+
modifier: modifier,
277+
modifiers: modifiers,
278+
attribute: attribute,
279+
attributes: attributes,
280+
addGeneratedCodeAttributes: addGeneratedCodeAttributes);
233281
}
234282

235283
private static ParameterSyntax ParameterWidget(
@@ -343,26 +391,85 @@ private static AccessorDeclarationSyntax AccessorWidget(SyntaxKind kind)
343391
return AccessorDeclaration(kind).WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
344392
}
345393

346-
private static TSyntax BaseWidgetDecoration<TSyntax>(
347-
TSyntax widget,
348-
SyntaxKind? modifier,
349-
IEnumerable<SyntaxKind>? modifiers,
350-
bool addGeneratedCodeAttributes) where TSyntax : MemberDeclarationSyntax
394+
private static AttributeSyntax AttributeWidget(
395+
string identifier,
396+
AttributeArgumentSyntax? argument = null,
397+
IEnumerable<AttributeArgumentSyntax>? arguments = null
398+
)
399+
{
400+
var attributeSyntax = Attribute(IdentifierName(identifier));
401+
402+
if (argument is not null)
403+
{
404+
var argumentList = attributeSyntax.ArgumentList ?? AttributeArgumentList();
405+
406+
attributeSyntax = attributeSyntax.WithArgumentList(argumentList
407+
.WithArguments(argumentList.Arguments.Add(argument)));
408+
}
409+
410+
if (arguments is not null)
411+
{
412+
var argumentList = attributeSyntax.ArgumentList ?? AttributeArgumentList();
413+
414+
attributeSyntax = attributeSyntax.WithArgumentList(argumentList
415+
.WithArguments(argumentList.Arguments.AddRange(arguments)));
416+
}
417+
418+
return attributeSyntax;
419+
}
420+
421+
private static TWidget BaseWidgetDecoration<TWidget>(
422+
TWidget widget,
423+
SyntaxKind? modifier = null,
424+
IEnumerable<SyntaxKind>? modifiers = null,
425+
AttributeSyntax? attribute = null,
426+
IEnumerable<AttributeSyntax>? attributes = null,
427+
bool addGeneratedCodeAttributes = true) where TWidget : MemberDeclarationSyntax
351428
{
352429
if (modifier is not null)
353430
{
354-
widget = (TSyntax) widget.WithModifiers(widget.Modifiers.Add(Token(modifier.Value)));
431+
widget = (TWidget) widget.WithModifiers(widget.Modifiers.Add(Token(modifier.Value)));
355432
}
356433

357434
if (modifiers is not null)
358435
{
359-
widget = (TSyntax) widget.WithModifiers(TokenList(modifiers.Select(Token)));
436+
widget = (TWidget) widget.WithModifiers(TokenList(modifiers.Select(Token)));
360437
}
361438

362-
return addGeneratedCodeAttributes ? GeneratedCodeAttributesWidget(widget) : widget;
439+
if (addGeneratedCodeAttributes)
440+
{
441+
var attributesList = GetGeneratedCodeAttributes(widget);
442+
443+
if (attribute is not null)
444+
{
445+
attributesList.Add(attribute);
446+
}
447+
448+
if (attributes is not null)
449+
{
450+
attributesList.AddRange(attributes);
451+
}
452+
453+
return (TWidget) widget.WithAttributeLists(widget.AttributeLists.AddRange(
454+
attributesList.Select(attributeSyntax => AttributeList(SingletonSeparatedList(attributeSyntax)))));
455+
}
456+
457+
if (attribute is not null)
458+
{
459+
widget = (TWidget) widget.WithAttributeLists(widget.AttributeLists.Add(
460+
AttributeList(SingletonSeparatedList(attribute))));
461+
}
462+
463+
if (attributes is not null)
464+
{
465+
widget = (TWidget) widget.WithAttributeLists(widget.AttributeLists.AddRange(
466+
attributes.Select(attributeSyntax => AttributeList(SingletonSeparatedList(attributeSyntax)))));
467+
}
468+
469+
return widget;
363470
}
364471

365-
private static TSyntax GeneratedCodeLeadingTrivia<TSyntax>(TSyntax node) where TSyntax : SyntaxNode
472+
private static TSyntax AddGeneratedCodeLeadingTrivia<TSyntax>(TSyntax node) where TSyntax : SyntaxNode
366473
{
367474
// Prepare the leading trivia for the generated compilation unit.
368475
// This will produce code as follows:
@@ -378,26 +485,28 @@ private static TSyntax GeneratedCodeLeadingTrivia<TSyntax>(TSyntax node) where T
378485
return node.WithLeadingTrivia(syntaxTriviaList);
379486
}
380487

381-
private static TSyntax GeneratedCodeAttributesWidget<TSyntax>(TSyntax member) where TSyntax : MemberDeclarationSyntax
488+
private static List<AttributeSyntax> GetGeneratedCodeAttributes<TMember>(TMember member) where TMember : MemberDeclarationSyntax
382489
{
383-
// [GeneratedCode] is always present.
384-
member = (TSyntax) member
385-
.WithoutLeadingTrivia()
386-
.AddAttributeLists(AttributeList(SingletonSeparatedList(
387-
Attribute(IdentifierName("global::System.CodeDom.Compiler.GeneratedCode"))
388-
.AddArgumentListArguments(
389-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(AssemblyName.Name))),
390-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(AssemblyName.Version.ToString())))))))
391-
.WithLeadingTrivia(member.GetLeadingTrivia());
490+
var attributes = new List<AttributeSyntax>
491+
{
492+
AttributeWidget(
493+
identifier: "global::System.CodeDom.Compiler.GeneratedCode",
494+
arguments: new[]
495+
{
496+
AttributeArgument(
497+
LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(AssemblyName.Name))),
498+
AttributeArgument(
499+
LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(AssemblyName.Version.ToString())))
500+
})
501+
};
392502

393503
// [ExcludeFromCodeCoverage] is not supported on interfaces and fields.
394504
if (member.Kind() is not SyntaxKind.InterfaceDeclaration and not SyntaxKind.FieldDeclaration)
395505
{
396-
member = (TSyntax) member
397-
.AddAttributeLists(AttributeList(SingletonSeparatedList(
398-
Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))));
506+
attributes.Add(AttributeWidget(
507+
identifier: "global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage"));
399508
}
400509

401-
return member;
510+
return attributes;
402511
}
403512
}

0 commit comments

Comments
 (0)