diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 4f9167d..2c4a54f 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,8 +1,9 @@ { - "enableAllProjectMcpServers": false, "permissions": { "allow": [ - "Bash(find:*)" + "Bash(find:*)", + "Bash(dotnet test:*)" ] - } + }, + "enableAllProjectMcpServers": false } \ No newline at end of file diff --git a/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs new file mode 100644 index 0000000..c705e59 --- /dev/null +++ b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs @@ -0,0 +1,36 @@ +#if ENABLE_COMMAND_FORGE_GENERATOR +namespace CommandForgeGenerator.Command +{ + public partial class TextCommand : ICommandForgeCommand + { + public const string Type = "text"; + public readonly CommandId CommandId; + + public readonly string Character; + public readonly string? Body; + public readonly string? VoiceId; + + + public static TextCommand Create(int commandId, global::Newtonsoft.Json.Linq.JToken json) + { + + var Character = (string)json["character"]; + var Body = json["body"] == null ? null : (string)json["body"]; + var VoiceId = json["voiceId"] == null ? null : (string)json["voiceId"]; + + + return new TextCommand(commandId, Character, Body, VoiceId); + } + + public TextCommand(int commandId, string Character, string? Body, string? VoiceId) + { + CommandId = (CommandId)commandId; + + this.Character = Character; + this.Body = Body; + this.VoiceId = VoiceId; + + } + } +} +#endif \ No newline at end of file diff --git a/CommandForgeGenerator.Tests/GenerateSampleUtl.cs b/CommandForgeGenerator.Tests/GenerateSampleUtl.cs new file mode 100644 index 0000000..af68e7d --- /dev/null +++ b/CommandForgeGenerator.Tests/GenerateSampleUtl.cs @@ -0,0 +1,6 @@ +namespace CommandForgeGenerator.Command; + +// 他の生成結果サンプルコマンドをコンパイルエラーにしないためのコード + +public interface ICommandForgeCommand { } +public enum CommandId{} \ No newline at end of file diff --git a/CommandForgeGenerator.Tests/GenerateTestCode.cs b/CommandForgeGenerator.Tests/GenerateTestCode.cs index d0e1db9..251b58c 100644 --- a/CommandForgeGenerator.Tests/GenerateTestCode.cs +++ b/CommandForgeGenerator.Tests/GenerateTestCode.cs @@ -1,40 +1,9 @@ +using System.IO; + namespace CommandForgeGenerator.Tests; public class GenerateTestCode { - public const string TextCommand = """ - #if ENABLE_COMMAND_FORGE_GENERATOR - namespace CommandForgeGenerator.Command - { - public partial class TextCommand : ICommandForgeCommand - { - public const string Type = "text"; - public readonly CommandId CommandId; - - public readonly string Character; - public readonly string Body; - - - public static TextCommand Create(int commandId, global::Newtonsoft.Json.Linq.JToken json) - { - - var Character = (string)json["character"]; - var Body = (string)json["body"]; - - - return new TextCommand(commandId, Character, Body); - } - - public TextCommand(int commandId, string Character, string Body) - { - CommandId = (CommandId)commandId; - - this.Character = Character; - this.Body = Body; - - } - } - } - #endif - """; + // プロジェクトファイルに存在する GenerateSampleTextCommand.cs を取得する + public static string TextCommandStr => File.ReadAllText("../../../GenerateSampleTextCommand.cs"); } \ No newline at end of file diff --git a/CommandForgeGenerator.Tests/Test.cs b/CommandForgeGenerator.Tests/Test.cs index 2d2ba98..590556a 100644 --- a/CommandForgeGenerator.Tests/Test.cs +++ b/CommandForgeGenerator.Tests/Test.cs @@ -65,7 +65,7 @@ public void GenerateTest() var codeFiles = CodeGenerator.Generate(commandsSchema); Assert.Equal(16, codeFiles.Count); - Assert.Equal(GenerateTestCode.TextCommand, codeFiles.FirstOrDefault(c => c.FileName == "TextCommand.g.cs").Code); + Assert.Equal(GenerateTestCode.TextCommandStr, codeFiles.FirstOrDefault(c => c.FileName == "TextCommand.g.cs").Code); #region Internal @@ -86,6 +86,10 @@ string GetSampleYaml() body: type: string multiline: true + voiceId: + type: string + multiline: true + required: false - id: emote label: エモート diff --git a/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs b/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs index 745938c..913e79b 100644 --- a/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs +++ b/CommandForgeGenerator/CodeGenerate/CodeGenerator.cs @@ -156,39 +156,42 @@ private static string GenerateCreateMethodTempVariables(List co else { // nullable の場合はnullチェックを追加 - properties.AppendLine($"var {property.CodeProperty}Token = json[\"{property.Name}\"];"); - - if (property.Type is CommandPropertyType.CommandId) + 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($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : (CommandId?)((int){property.CodeProperty}Token);"); + properties.AppendLine($"var {property.CodeProperty} = json[\"{property.Name}\"] == null ? null : (CommandId?)((int)json[\"{property.Name}\"]);"); } else if (property.Type is CommandPropertyType.Vector2) { - properties.AppendLine($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : new global::UnityEngine.Vector2((float){property.CodeProperty}Token[0], (float){property.CodeProperty}Token[1]);"); + 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($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : new global::UnityEngine.Vector3((float){property.CodeProperty}Token[0], (float){property.CodeProperty}Token[1], (float){property.CodeProperty}Token[2]);"); + 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($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : new global::UnityEngine.Vector4((float){property.CodeProperty}Token[0], (float){property.CodeProperty}Token[1], (float){property.CodeProperty}Token[2], (float){property.CodeProperty}Token[3]);"); + 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($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : new global::UnityEngine.Vector2Int((int){property.CodeProperty}Token[0], (int){property.CodeProperty}Token[1]);"); + 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($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : new global::UnityEngine.Vector3Int((int){property.CodeProperty}Token[0], (int){property.CodeProperty}Token[1], (int){property.CodeProperty}Token[2]);"); - } - else if (property.Type is CommandPropertyType.String) - { - properties.AppendLine($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : (string?){property.CodeProperty}Token;"); + 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($"{type} {property.CodeProperty} = {property.CodeProperty}Token?.Type == global::Newtonsoft.Json.Linq.JTokenType.Null ? null : ({type}){property.CodeProperty}Token;"); + properties.AppendLine($"var {property.CodeProperty} = json[\"{property.Name}\"] == null ? null : ({type})json[\"{property.Name}\"];"); } } } diff --git a/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs b/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs index cd8cdda..01d1500 100644 --- a/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs +++ b/CommandForgeGenerator/Semantic/CommandSemanticsLoader.cs @@ -90,11 +90,20 @@ CommandsSemantics ParseCommandsSchema(JsonObject root) _ => throw new Exception($"未知の property type \"{typeStr}\"") }; - // required フィールドを読み取る - var isRequired = true; - if (propObj.Nodes.ContainsKey("required") && propObj["required"] is JsonBoolean requiredNode) + // required フィールドを読み取る(デフォルトはfalse) + var isRequired = false; + if (propObj.Nodes.ContainsKey("required")) { - isRequired = requiredNode.Literal; + 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));