diff --git a/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/Runtime/UnityUxmlGenerator.dll b/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/Runtime/UnityUxmlGenerator.dll index 413a8eb..abb1cd1 100644 Binary files a/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/Runtime/UnityUxmlGenerator.dll and b/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/Runtime/UnityUxmlGenerator.dll differ diff --git a/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/package.json b/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/package.json index 470bbfa..6ba8c3a 100644 --- a/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/package.json +++ b/src/UnityUxmlGenerator.UnityPackage/Assets/Plugins/UnityUxmlGenerator/package.json @@ -2,7 +2,7 @@ "name": "com.chebanovdd.unityuxmlgenerator", "displayName": "Unity Uxml Generator", "author": { "name": "ChebanovDD", "url": "https://github.com/ChebanovDD" }, - "version": "0.0.5", + "version": "0.0.6", "unity": "2018.4", "description": "The Unity Uxml Generator allows you to generate 'UxmlFactory' and 'UxmlTraits' source code for a custom 'VisualElement'. Just mark elements with [UxmlElement] and [UxmlAttribute] attributes.", "keywords": [ "uxml", "source", "generator" ] diff --git a/src/UnityUxmlGenerator/Captures/UxmlTraitsCapture.cs b/src/UnityUxmlGenerator/Captures/UxmlTraitsCapture.cs index 1d7f9de..9e396f9 100644 --- a/src/UnityUxmlGenerator/Captures/UxmlTraitsCapture.cs +++ b/src/UnityUxmlGenerator/Captures/UxmlTraitsCapture.cs @@ -15,15 +15,15 @@ public UxmlTraitsCapture(ClassDeclarationSyntax @class, TypeSyntax baseClassType public TypeSyntax BaseClassType { get; } public List<(PropertyDeclarationSyntax Property, AttributeSyntax Attribute)> Properties { get; } - public string GetBaseClassName(out TypeSyntax? genericTypeSyntax) + public string GetBaseClassName(out IEnumerable? genericTypeArguments) { if (BaseClassType is GenericNameSyntax genericNameSyntax) { - genericTypeSyntax = genericNameSyntax.TypeArgumentList.Arguments[0]; + genericTypeArguments = genericNameSyntax.TypeArgumentList.Arguments; return genericNameSyntax.Identifier.Text; } - genericTypeSyntax = default; + genericTypeArguments = default; if (BaseClassType is IdentifierNameSyntax identifierNameSyntax) { diff --git a/src/UnityUxmlGenerator/Extensions/StringBuilderExtensions.cs b/src/UnityUxmlGenerator/Extensions/StringBuilderExtensions.cs new file mode 100644 index 0000000..b0fbc8f --- /dev/null +++ b/src/UnityUxmlGenerator/Extensions/StringBuilderExtensions.cs @@ -0,0 +1,79 @@ +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace UnityUxmlGenerator.Extensions; + +public static class StringBuilderExtensions +{ + public static void AppendGenericString(this StringBuilder stringBuilder, GeneratorExecutionContext context, + IEnumerable genericTypeArguments) + { + var isFirstArgument = true; + + stringBuilder.Append('<'); + + foreach (var genericClassTypeSyntax in genericTypeArguments) + { + if (isFirstArgument == false) + { + stringBuilder.Append(", "); + } + + isFirstArgument = false; + + switch (genericClassTypeSyntax) + { + case PredefinedTypeSyntax predefinedTypeSyntax: + AppendPredefinedTypeSyntax(stringBuilder, predefinedTypeSyntax); + break; + + case IdentifierNameSyntax identifierNameSyntax: + AppendIdentifierNameSyntax(stringBuilder, context, identifierNameSyntax); + break; + + case GenericNameSyntax genericTypeSyntax: + AppendGenericTypeSyntax(stringBuilder, context, genericTypeSyntax); + break; + } + } + + stringBuilder.Append('>'); + } + + private static void AppendPredefinedTypeSyntax(StringBuilder stringBuilder, + PredefinedTypeSyntax predefinedTypeSyntax) + { + stringBuilder.Append(predefinedTypeSyntax.Keyword.Text); + } + + private static void AppendIdentifierNameSyntax(StringBuilder stringBuilder, GeneratorExecutionContext context, + IdentifierNameSyntax identifierNameSyntax) + { + var genericClassName = identifierNameSyntax.Identifier.Text; + var genericClassNamespace = identifierNameSyntax.GetTypeNamespace(context); + + stringBuilder.Append("global::"); + stringBuilder.Append(genericClassNamespace); + stringBuilder.Append('.'); + stringBuilder.Append(genericClassName); + } + + private static void AppendGenericTypeSyntax(StringBuilder stringBuilder, GeneratorExecutionContext context, + GenericNameSyntax genericTypeSyntax) + { + var genericClassName = genericTypeSyntax.Identifier.Text; + var genericClassNamespace = genericTypeSyntax.GetTypeNamespace(context); + + if (string.IsNullOrWhiteSpace(genericClassNamespace) == false) + { + stringBuilder.Append("global::"); + stringBuilder.Append(genericClassNamespace); + stringBuilder.Append('.'); + } + + stringBuilder.Append(genericClassName); + + AppendGenericString(stringBuilder, context, genericTypeSyntax.TypeArgumentList.Arguments); + } +} \ No newline at end of file diff --git a/src/UnityUxmlGenerator/Extensions/SyntaxNodeExtensions.cs b/src/UnityUxmlGenerator/Extensions/SyntaxNodeExtensions.cs index df753d5..f940fee 100644 --- a/src/UnityUxmlGenerator/Extensions/SyntaxNodeExtensions.cs +++ b/src/UnityUxmlGenerator/Extensions/SyntaxNodeExtensions.cs @@ -52,6 +52,13 @@ when qualifiedNameSyntax.Right.Identifier.Text.Contains(attributeName): public static string? GetTypeNamespace(this SyntaxNode syntaxNode, GeneratorExecutionContext context) { - return GetTypeSymbol(syntaxNode, context)?.ContainingNamespace.ToString(); + var containingNamespace = GetTypeSymbol(syntaxNode, context)?.ContainingNamespace; + + if (containingNamespace is null || containingNamespace.IsGlobalNamespace) + { + return null; + } + + return containingNamespace.ToString(); } } \ No newline at end of file diff --git a/src/UnityUxmlGenerator/UxmlGenerator.Traits.cs b/src/UnityUxmlGenerator/UxmlGenerator.Traits.cs index b60c9ed..a2990d3 100644 --- a/src/UnityUxmlGenerator/UxmlGenerator.Traits.cs +++ b/src/UnityUxmlGenerator/UxmlGenerator.Traits.cs @@ -133,28 +133,23 @@ private static StatementSyntax GetAttributeValueAssignmentStatement(string prope private static string GetBaseClassName(GeneratorExecutionContext context, UxmlTraitsCapture capture) { - var baseClassName = capture.GetBaseClassName(out var genericClass); + var baseClassName = capture.GetBaseClassName(out var genericTypeArguments); var baseClassNamespace = capture.BaseClassType.GetTypeNamespace(context); - if (genericClass is null) + if (genericTypeArguments is null) { return $"global::{baseClassNamespace}.{baseClassName}"; } - if (genericClass is PredefinedTypeSyntax predefinedTypeSyntax) - { - return $"global::{baseClassNamespace}.{baseClassName}<{predefinedTypeSyntax.Keyword.Text}>"; - } + var stringBuilder = new StringBuilder(); - if (genericClass is IdentifierNameSyntax customTypeSyntax) - { - var genericClassName = customTypeSyntax.Identifier.Text; - var genericClassNamespace = customTypeSyntax.GetTypeNamespace(context); - - return $"global::{baseClassNamespace}.{baseClassName}"; - } + stringBuilder.Append("global::"); + stringBuilder.Append(baseClassNamespace); + stringBuilder.Append('.'); + stringBuilder.Append(baseClassName); + stringBuilder.AppendGenericString(context, genericTypeArguments); - return string.Empty; + return stringBuilder.ToString(); } private static bool TryGetUxmlAttributeInfo(GeneratorExecutionContext context, PropertyDeclarationSyntax property, diff --git a/src/UnityUxmlGenerator/UxmlGenerator.Widgets.cs b/src/UnityUxmlGenerator/UxmlGenerator.Widgets.cs index 2f68c76..23178f4 100644 --- a/src/UnityUxmlGenerator/UxmlGenerator.Widgets.cs +++ b/src/UnityUxmlGenerator/UxmlGenerator.Widgets.cs @@ -164,6 +164,7 @@ private static FieldDeclarationSyntax FieldWidget( { var variableDeclaration = VariableDeclarator(Identifier(identifier)); + // TODO: Change to BaseObjectCreationExpressionSyntax. if (initializer is not null) { variableDeclaration = variableDeclaration.WithInitializer(EqualsValueClause(ImplicitObjectCreationExpression()