From 0f87a76c15cf56b6fbf197c281a1e96c058c6087 Mon Sep 17 00:00:00 2001 From: sakastudio Date: Sun, 6 Jul 2025 16:58:38 +0900 Subject: [PATCH 1/5] =?UTF-8?q?=E3=82=B5=E3=83=B3=E3=83=97=E3=83=AB?= =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92=E5=A4=96=E3=81=AB=E5=87=BA?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GenerateSampleTextCommand.cs | 33 ++++++++++++++++ .../GenerateSampleUtl.cs | 6 +++ .../GenerateTestCode.cs | 39 ++----------------- CommandForgeGenerator.Tests/Test.cs | 2 +- 4 files changed, 44 insertions(+), 36 deletions(-) create mode 100644 CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs create mode 100644 CommandForgeGenerator.Tests/GenerateSampleUtl.cs diff --git a/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs new file mode 100644 index 0000000..1e4e190 --- /dev/null +++ b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs @@ -0,0 +1,33 @@ + #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 \ 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..081b56d 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("../../../CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs"); } \ No newline at end of file diff --git a/CommandForgeGenerator.Tests/Test.cs b/CommandForgeGenerator.Tests/Test.cs index 2d2ba98..9b24fc5 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 From c5aeacb7444622a5d3bc1c45c4dac7cae0bf26be Mon Sep 17 00:00:00 2001 From: sakastudio Date: Sun, 6 Jul 2025 17:02:12 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=E3=82=B5=E3=83=B3=E3=83=97=E3=83=AB?= =?UTF-8?q?=E3=81=ABrequired:=20true=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CommandForgeGenerator.Tests/Test.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/CommandForgeGenerator.Tests/Test.cs b/CommandForgeGenerator.Tests/Test.cs index 9b24fc5..cb185d8 100644 --- a/CommandForgeGenerator.Tests/Test.cs +++ b/CommandForgeGenerator.Tests/Test.cs @@ -86,6 +86,7 @@ string GetSampleYaml() body: type: string multiline: true + required: true - id: emote label: エモート From d5e46a1efc30eaa4c1cf58096b02313690c984bc Mon Sep 17 00:00:00 2001 From: sakastudio Date: Sun, 6 Jul 2025 17:08:04 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=B3?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=81=AEtext=E3=82=B3=E3=83=9E=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=81=AErequired=E3=82=92yaml=E3=81=8B=E3=82=89?= =?UTF-8?q?=E5=89=8A=E9=99=A4=E3=81=97=E3=80=81=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E7=94=A8=E3=81=AETextCommand=E3=82=AF=E3=83=A9=E3=82=B9?= =?UTF-8?q?=E3=82=92optional=E3=81=AB=E3=81=AA=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs | 8 ++++---- CommandForgeGenerator.Tests/GenerateTestCode.cs | 2 +- CommandForgeGenerator.Tests/Test.cs | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs index 1e4e190..dd06d47 100644 --- a/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs +++ b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs @@ -1,4 +1,4 @@ - #if ENABLE_COMMAND_FORGE_GENERATOR +#if ENABLE_COMMAND_FORGE_GENERATOR namespace CommandForgeGenerator.Command { public partial class TextCommand : ICommandForgeCommand @@ -7,20 +7,20 @@ public partial class TextCommand : ICommandForgeCommand public readonly CommandId CommandId; public readonly string Character; - public readonly string Body; + 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"]; + var Body = json["body"] == null ? null : (string)json["body"]; return new TextCommand(commandId, Character, Body); } - public TextCommand(int commandId, string Character, string Body) + public TextCommand(int commandId, string Character, string? Body) { CommandId = (CommandId)commandId; diff --git a/CommandForgeGenerator.Tests/GenerateTestCode.cs b/CommandForgeGenerator.Tests/GenerateTestCode.cs index 081b56d..251b58c 100644 --- a/CommandForgeGenerator.Tests/GenerateTestCode.cs +++ b/CommandForgeGenerator.Tests/GenerateTestCode.cs @@ -5,5 +5,5 @@ namespace CommandForgeGenerator.Tests; public class GenerateTestCode { // プロジェクトファイルに存在する GenerateSampleTextCommand.cs を取得する - public static string TextCommandStr => File.ReadAllText("../../../CommandForgeGenerator.Tests/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 cb185d8..9b24fc5 100644 --- a/CommandForgeGenerator.Tests/Test.cs +++ b/CommandForgeGenerator.Tests/Test.cs @@ -86,7 +86,6 @@ string GetSampleYaml() body: type: string multiline: true - required: true - id: emote label: エモート From f80c8cc7faaec4b2aa2a35c38b96769c3204c239 Mon Sep 17 00:00:00 2001 From: sakastudio Date: Sun, 6 Jul 2025 17:28:29 +0900 Subject: [PATCH 4/5] =?UTF-8?q?required=E3=81=8Cfalse=E3=81=A7=E3=81=82?= =?UTF-8?q?=E3=82=8B=E3=82=B5=E3=83=B3=E3=83=97=E3=83=AB=E3=82=82=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs | 7 +++++-- CommandForgeGenerator.Tests/Test.cs | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs index dd06d47..c705e59 100644 --- a/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs +++ b/CommandForgeGenerator.Tests/GenerateSampleTextCommand.cs @@ -8,6 +8,7 @@ public partial class TextCommand : ICommandForgeCommand public readonly string Character; public readonly string? Body; + public readonly string? VoiceId; public static TextCommand Create(int commandId, global::Newtonsoft.Json.Linq.JToken json) @@ -15,17 +16,19 @@ public static TextCommand Create(int commandId, global::Newtonsoft.Json.Linq.JTo 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); + return new TextCommand(commandId, Character, Body, VoiceId); } - public TextCommand(int commandId, string Character, string? Body) + public TextCommand(int commandId, string Character, string? Body, string? VoiceId) { CommandId = (CommandId)commandId; this.Character = Character; this.Body = Body; + this.VoiceId = VoiceId; } } diff --git a/CommandForgeGenerator.Tests/Test.cs b/CommandForgeGenerator.Tests/Test.cs index 9b24fc5..590556a 100644 --- a/CommandForgeGenerator.Tests/Test.cs +++ b/CommandForgeGenerator.Tests/Test.cs @@ -86,6 +86,10 @@ string GetSampleYaml() body: type: string multiline: true + voiceId: + type: string + multiline: true + required: false - id: emote label: エモート From 921ba5522c842847165f033dc4c0c9df9e85eefa Mon Sep 17 00:00:00 2001 From: sakastudio Date: Sun, 6 Jul 2025 18:04:22 +0900 Subject: [PATCH 5/5] =?UTF-8?q?required=E3=81=AE=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E7=94=9F=E6=88=90=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 7 +++-- .../CodeGenerate/CodeGenerator.cs | 31 ++++++++++--------- .../Semantic/CommandSemanticsLoader.cs | 17 +++++++--- 3 files changed, 34 insertions(+), 21 deletions(-) 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/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));