diff --git a/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs b/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs index 72a07ce..913e79b 100644 --- a/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs +++ b/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs @@ -101,7 +101,7 @@ private static string GeneratePropertiesCode(List commandProper properties.AppendLine(); foreach (var property in commandProperties) { - var type = GetTypeCode(property.Type); + var type = GetTypeCode(property.Type, property.IsRequired); properties.AppendLine($"public readonly {type} {property.CodeProperty};"); } @@ -114,39 +114,85 @@ private static string GenerateCreateMethodTempVariables(List co properties.AppendLine(); foreach (var property in commandProperties) { - var type = GetTypeCode(property.Type); - if (property.Type is CommandPropertyType.CommandId) - { - properties.AppendLine($"var {property.CodeProperty} = (CommandId)((int)json[\"{property.Name}\"]);"); - } - else if (property.Type is CommandPropertyType.Vector2) - { - properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); - properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector2((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1]);"); - } - else if (property.Type is CommandPropertyType.Vector3) - { - properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); - properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector3((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1], (float){property.CodeProperty}Array[2]);"); - } - else if (property.Type is CommandPropertyType.Vector4) - { - properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); - properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector4((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1], (float){property.CodeProperty}Array[2], (float){property.CodeProperty}Array[3]);"); - } - else if (property.Type is CommandPropertyType.Vector2Int) - { - properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); - properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector2Int((int){property.CodeProperty}Array[0], (int){property.CodeProperty}Array[1]);"); - } - else if (property.Type is CommandPropertyType.Vector3Int) + var type = GetTypeCode(property.Type, property.IsRequired); + + if (property.IsRequired) { - properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); - properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector3Int((int){property.CodeProperty}Array[0], (int){property.CodeProperty}Array[1], (int){property.CodeProperty}Array[2]);"); + // required の場合は従来通り + if (property.Type is CommandPropertyType.CommandId) + { + properties.AppendLine($"var {property.CodeProperty} = (CommandId)((int)json[\"{property.Name}\"]);"); + } + else if (property.Type is CommandPropertyType.Vector2) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector2((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1]);"); + } + else if (property.Type is CommandPropertyType.Vector3) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector3((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1], (float){property.CodeProperty}Array[2]);"); + } + else if (property.Type is CommandPropertyType.Vector4) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector4((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1], (float){property.CodeProperty}Array[2], (float){property.CodeProperty}Array[3]);"); + } + else if (property.Type is CommandPropertyType.Vector2Int) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector2Int((int){property.CodeProperty}Array[0], (int){property.CodeProperty}Array[1]);"); + } + else if (property.Type is CommandPropertyType.Vector3Int) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = new global::UnityEngine.Vector3Int((int){property.CodeProperty}Array[0], (int){property.CodeProperty}Array[1], (int){property.CodeProperty}Array[2]);"); + } + else + { + properties.AppendLine($"var {property.CodeProperty} = ({type})json[\"{property.Name}\"];"); + } } else { - properties.AppendLine($"var {property.CodeProperty} = ({type})json[\"{property.Name}\"];"); + // nullable の場合はnullチェックを追加 + if (property.Type is CommandPropertyType.String) + { + properties.AppendLine($"var {property.CodeProperty} = json[\"{property.Name}\"] == null ? null : (string)json[\"{property.Name}\"];"); + } + else if (property.Type is CommandPropertyType.CommandId) + { + properties.AppendLine($"var {property.CodeProperty} = json[\"{property.Name}\"] == null ? null : (CommandId?)((int)json[\"{property.Name}\"]);"); + } + else if (property.Type is CommandPropertyType.Vector2) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = {property.CodeProperty}Array == null ? null : new global::UnityEngine.Vector2((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1]);"); + } + else if (property.Type is CommandPropertyType.Vector3) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = {property.CodeProperty}Array == null ? null : new global::UnityEngine.Vector3((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1], (float){property.CodeProperty}Array[2]);"); + } + else if (property.Type is CommandPropertyType.Vector4) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = {property.CodeProperty}Array == null ? null : new global::UnityEngine.Vector4((float){property.CodeProperty}Array[0], (float){property.CodeProperty}Array[1], (float){property.CodeProperty}Array[2], (float){property.CodeProperty}Array[3]);"); + } + else if (property.Type is CommandPropertyType.Vector2Int) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = {property.CodeProperty}Array == null ? null : new global::UnityEngine.Vector2Int((int){property.CodeProperty}Array[0], (int){property.CodeProperty}Array[1]);"); + } + else if (property.Type is CommandPropertyType.Vector3Int) + { + properties.AppendLine($"var {property.CodeProperty}Array = json[\"{property.Name}\"];"); + properties.AppendLine($"var {property.CodeProperty} = {property.CodeProperty}Array == null ? null : new global::UnityEngine.Vector3Int((int){property.CodeProperty}Array[0], (int){property.CodeProperty}Array[1], (int){property.CodeProperty}Array[2]);"); + } + else + { + properties.AppendLine($"var {property.CodeProperty} = json[\"{property.Name}\"] == null ? null : ({type})json[\"{property.Name}\"];"); + } } } @@ -169,7 +215,7 @@ public static string GenerateConstructorPropertiesCode(List com var properties = new StringBuilder(); foreach (var property in commandProperties) { - var type = GetTypeCode(property.Type); + var type = GetTypeCode(property.Type, property.IsRequired); properties.Append($", {type} {property.CodeProperty}"); } @@ -189,9 +235,9 @@ private static string GenerateConstructSetPropertiesCode(List c return construct.ToString(); } - private static string GetTypeCode(CommandPropertyType type) + private static string GetTypeCode(CommandPropertyType type, bool isRequired) { - return type switch + var baseType = type switch { CommandPropertyType.String => "string", CommandPropertyType.Int => "int", @@ -205,6 +251,20 @@ private static string GetTypeCode(CommandPropertyType type) CommandPropertyType.Vector3Int => "global::UnityEngine.Vector3Int", _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) }; + + // 値型でrequiredでない場合は nullable にする + if (!isRequired && type != CommandPropertyType.String) + { + return baseType + "?"; + } + + // 参照型でも明示的に nullable にする(C# 8.0以降) + if (!isRequired && type == CommandPropertyType.String) + { + return baseType + "?"; + } + + return baseType; } public static string GenerateLoaderCode(CommandsSemantics commandsSemantics) diff --git a/CommandForgeGenerator/CommandForgeGenerator.csproj b/CommandForgeGenerator/CommandForgeGenerator.csproj index 2110196..be65098 100644 --- a/CommandForgeGenerator/CommandForgeGenerator.csproj +++ b/CommandForgeGenerator/CommandForgeGenerator.csproj @@ -18,7 +18,7 @@ CommandForge Generator Moorestech - 1.0.6 + 1.0.5 CommandForgeEditorのcommands.yamlのC#コードを生成するSourceGenerator https://github.com/moorestech/CommandForgeGenerator https://github.com/moorestech/CommandForgeGenerator diff --git a/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs b/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs index 89f39d5..01d1500 100644 --- a/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs +++ b/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs @@ -90,7 +90,23 @@ CommandsSemantics ParseCommandsSchema(JsonObject root) _ => throw new Exception($"未知の property type \"{typeStr}\"") }; - properties.Add(new CommandProperty(mappedType, propName)); + // required フィールドを読み取る(デフォルトはfalse) + var isRequired = false; + if (propObj.Nodes.ContainsKey("required")) + { + var requiredVal = propObj["required"]; + if (requiredVal is JsonBoolean requiredBool) + { + isRequired = requiredBool.Literal; + } + else if (requiredVal is JsonString requiredStr) + { + // YAMLが文字列としてbooleanを返す場合がある + isRequired = requiredStr.Literal.ToLowerInvariant() == "true"; + } + } + + properties.Add(new CommandProperty(mappedType, propName, isRequired)); } commands.Add(new CommandSemantics(commandName, properties)); diff --git a/CommandForgeGenerator/Semantic/CommandsSemantics.cs b/CommandForgeGenerator/Semantic/CommandsSemantics.cs index 3c2e413..1fa7c4b 100644 --- a/CommandForgeGenerator/Semantic/CommandsSemantics.cs +++ b/CommandForgeGenerator/Semantic/CommandsSemantics.cs @@ -28,13 +28,15 @@ public CommandSemantics(string name, List properties) public class CommandProperty{ public readonly string Name; public readonly CommandPropertyType Type; + public readonly bool IsRequired; public string CodeProperty => Name.ToUpper(0); - public CommandProperty(CommandPropertyType type, string name) + public CommandProperty(CommandPropertyType type, string name, bool isRequired) { Type = type; Name = name; + IsRequired = isRequired; } } diff --git a/CommandForgeGenerator/Semantic/ReservedCommandSemantics.cs b/CommandForgeGenerator/Semantic/ReservedCommandSemantics.cs index 46727e7..0969cdd 100644 --- a/CommandForgeGenerator/Semantic/ReservedCommandSemantics.cs +++ b/CommandForgeGenerator/Semantic/ReservedCommandSemantics.cs @@ -8,8 +8,8 @@ public static List GetReservedCommand() { var groupStart = new CommandSemantics("group_start", new List() { - new(CommandPropertyType.String, "groupName"), - new(CommandPropertyType.Bool, "isCollapsed"), + new(CommandPropertyType.String, "groupName", true), + new(CommandPropertyType.Bool, "isCollapsed", true), }); var groupEnd = new CommandSemantics("group_end", new List()); return new List(){groupStart, groupEnd};