diff --git a/src/KubeOps.Generator/SyntaxReceiver/KubernetesEntitySyntaxReceiver.cs b/src/KubeOps.Generator/SyntaxReceiver/KubernetesEntitySyntaxReceiver.cs index f98bcc0d..586565b9 100644 --- a/src/KubeOps.Generator/SyntaxReceiver/KubernetesEntitySyntaxReceiver.cs +++ b/src/KubeOps.Generator/SyntaxReceiver/KubernetesEntitySyntaxReceiver.cs @@ -11,7 +11,7 @@ internal sealed class KubernetesEntitySyntaxReceiver : ISyntaxContextReceiver { private const string KindName = "Kind"; private const string GroupName = "Group"; - private const string PluralName = "Plural"; + private const string PluralName = "PluralName"; private const string VersionName = "ApiVersion"; private const string DefaultVersion = "v1"; @@ -28,15 +28,24 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) Entities.Add(new( cls, - GetArgumentValue(attr, KindName) ?? cls.Identifier.ToString(), - GetArgumentValue(attr, VersionName) ?? DefaultVersion, - GetArgumentValue(attr, GroupName), - GetArgumentValue(attr, PluralName))); + GetArgumentValue(context, attr, KindName) ?? cls.Identifier.ToString(), + GetArgumentValue(context, attr, VersionName) ?? DefaultVersion, + GetArgumentValue(context, attr, GroupName), + GetArgumentValue(context, attr, PluralName))); } - private static string? GetArgumentValue(AttributeSyntax attr, string argName) => - attr.ArgumentList?.Arguments.FirstOrDefault(a => a.NameEquals?.Name.ToString() == argName) is - { Expression: LiteralExpressionSyntax { Token.ValueText: { } value } } - ? value - : null; + private static string? GetArgumentValue(GeneratorSyntaxContext context, AttributeSyntax attr, string argName) + { + var argument = attr.ArgumentList?.Arguments.FirstOrDefault(a => a.NameEquals?.Name.ToString() == argName)?.Expression; + if (argument != null) + { + var constValue = context.SemanticModel.GetConstantValue(argument); + if (constValue is { HasValue: true, Value: string attrValue }) + { + return attrValue; + } + } + + return null; + } } diff --git a/test/KubeOps.Generator.Test/EntityInitializerGenerator.Test.cs b/test/KubeOps.Generator.Test/EntityInitializerGenerator.Test.cs index 3e65a430..34d319dc 100644 --- a/test/KubeOps.Generator.Test/EntityInitializerGenerator.Test.cs +++ b/test/KubeOps.Generator.Test/EntityInitializerGenerator.Test.cs @@ -336,4 +336,82 @@ public V1TestEntity() .ToString().ReplaceLineEndings(); result.Should().Be(expectedResult); } + + [Fact] + public void Should_Generate_Default_Ctor_For_Partial_Entity_With_Metadata_Const() + { + var inputCompilation = """ + [KubernetesEntity(Group = KubeGroup, ApiVersion = KubeApiVersion, Kind = KubeKind, PluralName = KubePluralName)] + public partial class V1TestEntity : IKubernetesObject + { + public const string KubeApiVersion = "v1"; + public const string KubeGroup = "testing.dev"; + public const string KubeKind = "TestEntity"; + public const string KubePluralName = "testentities"; + } + """.CreateCompilation(); + var expectedResult = """ + // + // This code was generated by a tool. + // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. + // + #pragma warning disable CS1591 + public partial class V1TestEntity + { + public V1TestEntity() + { + ApiVersion = "testing.dev/v1"; + Kind = "TestEntity"; + } + } + """.ReplaceLineEndings(); + + var driver = CSharpGeneratorDriver.Create(new EntityInitializerGenerator()); + driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var output, out ImmutableArray _); + + var result = output.SyntaxTrees + .First(s => s.FilePath.Contains("V1TestEntity.init.g.cs")) + .ToString().ReplaceLineEndings(); + result.Should().Be(expectedResult); + } + + [Fact] + public void Should_Generate_Default_Ctor_For_Partial_Entity_With_External_Metadata_Const() + { + var inputCompilation = """ + internal static class Constants + { + public const string KubeApiVersion = "v1"; + public const string KubeGroup = "testing.dev"; + public const string KubeKind = "TestEntity"; + public const string KubePluralName = "testentities"; + } + + [KubernetesEntity(Group = Constants.KubeGroup, ApiVersion = Constants.KubeApiVersion, Kind = Constants.KubeKind, PluralName = Constants.KubePluralName)] + public partial class V1TestEntity : IKubernetesObject; + """.CreateCompilation(); + var expectedResult = """ + // + // This code was generated by a tool. + // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. + // + #pragma warning disable CS1591 + public partial class V1TestEntity + { + public V1TestEntity() + { + ApiVersion = "testing.dev/v1"; + Kind = "TestEntity"; + } + } + """.ReplaceLineEndings(); + + var driver = CSharpGeneratorDriver.Create(new EntityInitializerGenerator()); + driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var output, out ImmutableArray _); + + var result = output.SyntaxTrees + .First(s => s.FilePath.Contains("V1TestEntity.init.g.cs")) + .ToString().ReplaceLineEndings(); + result.Should().Be(expectedResult); + } }