From ed755e8c6485f3210b75acfc37f2d1c4cfc50da0 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:34:00 +0900 Subject: [PATCH 01/12] Add opt-in ShapeTag emission --- src/TypeGenerationModel.cs | 4 ++ src/ZeroSerializerGenerator.cs | 60 ++++++++++++++++++++++++++-- tests/SerializationModels.cs | 10 ++--- tests/ShapeTagEmissionTests.cs | 72 ++++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 tests/ShapeTagEmissionTests.cs diff --git a/src/TypeGenerationModel.cs b/src/TypeGenerationModel.cs index 65327d8..f2ba27c 100644 --- a/src/TypeGenerationModel.cs +++ b/src/TypeGenerationModel.cs @@ -15,6 +15,7 @@ internal TypeGenerationModel( string qualifiedSourceTypeName, string viewTypeName, bool isEffectivelyPublic, + bool emitShapeTag, bool isBlittableStruct, int blittableStructByteCount) { @@ -22,6 +23,7 @@ internal TypeGenerationModel( QualifiedSourceTypeName = qualifiedSourceTypeName; ViewTypeName = viewTypeName; IsEffectivelyPublic = isEffectivelyPublic; + EmitShapeTag = emitShapeTag; IsBlittableStruct = isBlittableStruct; BlittableStructByteCount = blittableStructByteCount; } @@ -34,6 +36,8 @@ internal TypeGenerationModel( internal bool IsEffectivelyPublic { get; } + internal bool EmitShapeTag { get; } + internal bool IsBlittableStruct { get; } internal int BlittableStructByteCount { get; } diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 3a63d4e..41cd0aa 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -111,6 +111,10 @@ public void Execute(GeneratorExecutionContext executionContext) injectedAttributeSourceBuilder.AppendLine(" Inherited = false)]"); injectedAttributeSourceBuilder.AppendLine($"internal sealed class {SerializerAttributeName} : Attribute"); injectedAttributeSourceBuilder.OpenBlock(); + injectedAttributeSourceBuilder.AppendLine("[Obsolete(\"Emitting string representation of the type will expose internal details in the resulting assembly. Consider using `ShapeHash` instead, or using `#if DEBUG` directive to prevent emitting on release build.\")]"); + injectedAttributeSourceBuilder.AppendLine("public bool EmitShapeTag;"); + injectedAttributeSourceBuilder.AppendLine(); + injectedAttributeSourceBuilder.AppendLine($"public {SerializerAttributeName}() {{ }}"); injectedAttributeSourceBuilder.CloseBlock(); injectedAttributeSourceBuilder.CloseBlock(); executionContext.AddSource( @@ -285,6 +289,7 @@ private static TypeGenerationModel CreateGenerationModel( qualifiedSourceTypeName, serializableType.Name + "View", IsEffectivelyPublic(serializableType), + ShouldEmitShapeTag(serializableType), isBlittableStruct, isBlittableStruct ? blittableStructByteCount : 0); @@ -365,6 +370,42 @@ private static TypeGenerationModel CreateGenerationModel( return generationModel; } + private static bool ShouldEmitShapeTag(INamedTypeSymbol serializableType) + { + foreach (SyntaxReference syntaxReference in serializableType.DeclaringSyntaxReferences) + { + if (syntaxReference.GetSyntax() is not TypeDeclarationSyntax declaration) + { + continue; + } + + foreach (AttributeListSyntax attributeList in declaration.AttributeLists) + { + foreach (AttributeSyntax attribute in attributeList.Attributes) + { + string attributeName = attribute.Name.ToString(); + if (!attributeName.EndsWith(SerializerName, StringComparison.Ordinal) + && !attributeName.EndsWith(SerializerAttributeName, StringComparison.Ordinal)) + { + continue; + } + + foreach (AttributeArgumentSyntax argument in attribute.ArgumentList?.Arguments + ?? default(SeparatedSyntaxList)) + { + if (argument.NameEquals?.Name.Identifier.ValueText == "EmitShapeTag" + && argument.Expression.IsKind(SyntaxKind.TrueLiteralExpression)) + { + return true; + } + } + } + } + } + + return false; + } + private static FieldGenerationModel? CreatePropertyGenerationModel( IPropertySymbol serializableProperty, HashSet allSerializableTypes) @@ -913,9 +954,12 @@ private static void EmitView( sourceBuilder.AppendLine("/// "); sourceBuilder.AppendLine($"/// Provides a deserialized view of ."); sourceBuilder.AppendLine("/// "); - sourceBuilder.AppendLine("/// "); - sourceBuilder.AppendLine($"/// ShapeTag: {shapeTag}"); - sourceBuilder.AppendLine("/// "); + if (generationModel.EmitShapeTag) + { + sourceBuilder.AppendLine("/// "); + sourceBuilder.AppendLine($"/// ShapeTag: {shapeTag}"); + sourceBuilder.AppendLine("/// "); + } sourceBuilder.AppendLine($"{viewAccessibility} readonly struct {generationModel.ViewTypeName}"); sourceBuilder.OpenBlock(); sourceBuilder.AppendLine("/// "); @@ -925,7 +969,15 @@ private static void EmitView( sourceBuilder.AppendLine($"public const int RequiredByteLength = {requiredByteLength};"); sourceBuilder.AppendLine($"public const bool IsBlittable = {generationModel.IsBlittableStruct.ToString().ToLowerInvariant()};"); uint shapeHash = XXHash32.HashToUInt32(shapeTag); - sourceBuilder.AppendLine($"public const string ShapeTag = \"{shapeTag}\";"); + if (generationModel.EmitShapeTag) + { + sourceBuilder.AppendLine($"public const string ShapeTag = \"{shapeTag}\";"); + } + else + { + sourceBuilder.AppendLine("// To emit this, set EmitShapeTag = true on ZeroSerializerAttribute."); + sourceBuilder.AppendLine($"// public const string ShapeTag = \"{shapeTag}\";"); + } sourceBuilder.AppendLine($"public const uint ShapeHash = {shapeHash}U;"); sourceBuilder.AppendLine(); // ReadOnlyMemory keeps the borrowed byte array reusable by ordinary and nested View structs without allocation. diff --git a/tests/SerializationModels.cs b/tests/SerializationModels.cs index a253de6..f210139 100644 --- a/tests/SerializationModels.cs +++ b/tests/SerializationModels.cs @@ -22,7 +22,7 @@ public enum SignedState : short Positive = 5, } -[ZeroSerializer] +[ZeroSerializer(EmitShapeTag = true)] public sealed class PrimitiveRecord { public bool Boolean { get; init; } @@ -50,7 +50,7 @@ public sealed class PrimitiveRecord public double Double { get; init; } } -[ZeroSerializer] +[ZeroSerializer(EmitShapeTag = true)] public sealed class EnumClass { public ByteState ByteState { get; init; } @@ -73,7 +73,7 @@ public EnumStruct(ByteState byteState, SignedState signedState) } [StructLayout(LayoutKind.Sequential, Pack = 1)] -[ZeroSerializer] +[ZeroSerializer(EmitShapeTag = true)] public struct PackedRecord { public int Number { get; init; } @@ -81,7 +81,7 @@ public struct PackedRecord public SignedState State { get; init; } } -[ZeroSerializer] +[ZeroSerializer(EmitShapeTag = true)] public sealed class PackedContainer { public PackedRecord Value { get; init; } @@ -267,7 +267,7 @@ public struct EmptyBlittableStruct { } -[ZeroSerializer] +[ZeroSerializer(EmitShapeTag = true)] public sealed class SchemaSignatureTestsModel { // 1. blittable and non-blittable nested type combo diff --git a/tests/ShapeTagEmissionTests.cs b/tests/ShapeTagEmissionTests.cs new file mode 100644 index 0000000..4669529 --- /dev/null +++ b/tests/ShapeTagEmissionTests.cs @@ -0,0 +1,72 @@ +// Licensed under the Apache-2.0 License +// https://github.com/sator-imaging/ZeroSerializer + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using System; +using System.Linq; +using Xunit; +using ZeroSerializer.Generator; + +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + +namespace ZeroSerializer.Tests; + +public class ShapeTagEmissionTests +{ + [Fact] + public void ShapeTagIsCommentedOutByDefault() + { + string generatedView = GenerateView("[ZeroSerializer.ZeroSerializer] public class Record { public int Value { get; set; } }"); + + Assert.DoesNotContain("/// ", generatedView); + Assert.Contains("// To emit this, set EmitShapeTag = true on ZeroSerializerAttribute.", generatedView); + Assert.Contains("// public const string ShapeTag = \"v1/{int}\";", generatedView); + Assert.Contains("public const uint ShapeHash = ", generatedView); + } + + [Fact] + public void ShapeTagAndRemarksAreEmittedWhenRequested() + { + string generatedView = GenerateView("[ZeroSerializer.ZeroSerializer(EmitShapeTag = true)] public class Record { public int Value { get; set; } }"); + + Assert.Contains("/// ", generatedView); + Assert.Contains("/// ShapeTag: v1/{int}", generatedView); + Assert.Contains("public const string ShapeTag = \"v1/{int}\";", generatedView); + Assert.DoesNotContain("// public const string ShapeTag", generatedView); + } + + [Fact] + public void InjectedAttributeExposesObsoleteEmitShapeTagField() + { + GeneratorDriverRunResult result = RunGenerator("public class Record { }"); + string generatedAttribute = result.Results[0].GeneratedSources + .Single(source => source.HintName == "- ZeroSerializerAttribute.g.cs") + .SourceText + .ToString(); + + Assert.Contains("public bool EmitShapeTag;", generatedAttribute); + Assert.Contains("[Obsolete(\"Emitting string representation of the type will expose internal details", generatedAttribute); + Assert.Contains("public ZeroSerializerAttribute() { }", generatedAttribute); + } + + private static string GenerateView(string source) + { + GeneratorDriverRunResult result = RunGenerator(source); + return result.Results[0].GeneratedSources + .Single(generatedSource => generatedSource.HintName == "Record.ZeroSerializer.g.cs") + .SourceText + .ToString(); + } + + private static GeneratorDriverRunResult RunGenerator(string source) + { + SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source); + CSharpCompilation compilation = CSharpCompilation.Create( + "ShapeTagEmissionTests", + new[] { syntaxTree }, + new[] { MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location) }); + GeneratorDriver driver = CSharpGeneratorDriver.Create(new ZeroSerializerGenerator()); + return driver.RunGenerators(compilation).GetRunResult(); + } +} From bb64554c5fee3e8cc33b4262fdb5e2f644e11d42 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:39:48 +0900 Subject: [PATCH 02/12] Apply suggestion from @sator-imaging --- src/ZeroSerializerGenerator.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 41cd0aa..ea53ed7 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -390,13 +390,15 @@ private static bool ShouldEmitShapeTag(INamedTypeSymbol serializableType) continue; } - foreach (AttributeArgumentSyntax argument in attribute.ArgumentList?.Arguments - ?? default(SeparatedSyntaxList)) + if (attribute.ArgumentList != null) { - if (argument.NameEquals?.Name.Identifier.ValueText == "EmitShapeTag" - && argument.Expression.IsKind(SyntaxKind.TrueLiteralExpression)) + foreach (AttributeArgumentSyntax argument in attribute.ArgumentList.Arguments) { - return true; + if (argument.NameEquals?.Name.Identifier.ValueText == "EmitShapeTag" && + argument.Expression.IsKind(SyntaxKind.TrueLiteralExpression)) + { + return true; + } } } } From edf0209b4103e7c11367c7bf138bbf81fec9832b Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:40:33 +0900 Subject: [PATCH 03/12] Apply suggestion from @sator-imaging --- src/ZeroSerializerGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index ea53ed7..a824fa9 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -384,8 +384,8 @@ private static bool ShouldEmitShapeTag(INamedTypeSymbol serializableType) foreach (AttributeSyntax attribute in attributeList.Attributes) { string attributeName = attribute.Name.ToString(); - if (!attributeName.EndsWith(SerializerName, StringComparison.Ordinal) - && !attributeName.EndsWith(SerializerAttributeName, StringComparison.Ordinal)) + if (!attributeName.EndsWith(SerializerName, StringComparison.Ordinal) && + !attributeName.EndsWith(SerializerAttributeName, StringComparison.Ordinal)) { continue; } From 211d692887a567fa96b9e06e4be19174e5b3ed61 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:42:49 +0900 Subject: [PATCH 04/12] Apply suggestion from @sator-imaging --- src/ZeroSerializerGenerator.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index a824fa9..802c925 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -390,15 +390,17 @@ private static bool ShouldEmitShapeTag(INamedTypeSymbol serializableType) continue; } - if (attribute.ArgumentList != null) + if (attribute.ArgumentList == null) { - foreach (AttributeArgumentSyntax argument in attribute.ArgumentList.Arguments) - { - if (argument.NameEquals?.Name.Identifier.ValueText == "EmitShapeTag" && + continue; + } + + foreach (AttributeArgumentSyntax argument in attribute.ArgumentList.Arguments) + { + if (argument.NameEquals?.Name.Identifier.ValueText == "EmitShapeTag" && argument.Expression.IsKind(SyntaxKind.TrueLiteralExpression)) - { - return true; - } + { + return true; } } } From 0675a6bf24a127d0b71404d9da443707bec41c4e Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:45:43 +0900 Subject: [PATCH 05/12] Apply suggestion from @sator-imaging --- src/ZeroSerializerGenerator.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 802c925..058cb09 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -973,15 +973,11 @@ private static void EmitView( sourceBuilder.AppendLine($"public const int RequiredByteLength = {requiredByteLength};"); sourceBuilder.AppendLine($"public const bool IsBlittable = {generationModel.IsBlittableStruct.ToString().ToLowerInvariant()};"); uint shapeHash = XXHash32.HashToUInt32(shapeTag); - if (generationModel.EmitShapeTag) - { - sourceBuilder.AppendLine($"public const string ShapeTag = \"{shapeTag}\";"); - } - else + if (!generationModel.EmitShapeTag) { sourceBuilder.AppendLine("// To emit this, set EmitShapeTag = true on ZeroSerializerAttribute."); - sourceBuilder.AppendLine($"// public const string ShapeTag = \"{shapeTag}\";"); } + sourceBuilder.AppendLine($"{(!generationModel.EmitShapeTag ? "// " : string.Empty)}public const string ShapeTag = \"{shapeTag}\";"); sourceBuilder.AppendLine($"public const uint ShapeHash = {shapeHash}U;"); sourceBuilder.AppendLine(); // ReadOnlyMemory keeps the borrowed byte array reusable by ordinary and nested View structs without allocation. From 754bc9f1823791d1c5368d60e2602aec7cd2eb5a Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:47:15 +0900 Subject: [PATCH 06/12] Apply suggestion from @sator-imaging --- src/ZeroSerializerGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZeroSerializerGenerator.cs b/src/ZeroSerializerGenerator.cs index 058cb09..8590075 100644 --- a/src/ZeroSerializerGenerator.cs +++ b/src/ZeroSerializerGenerator.cs @@ -975,7 +975,7 @@ private static void EmitView( uint shapeHash = XXHash32.HashToUInt32(shapeTag); if (!generationModel.EmitShapeTag) { - sourceBuilder.AppendLine("// To emit this, set EmitShapeTag = true on ZeroSerializerAttribute."); + sourceBuilder.AppendLine("// To emit this, `set EmitShapeTag = true` on ZeroSerializerAttribute."); } sourceBuilder.AppendLine($"{(!generationModel.EmitShapeTag ? "// " : string.Empty)}public const string ShapeTag = \"{shapeTag}\";"); sourceBuilder.AppendLine($"public const uint ShapeHash = {shapeHash}U;"); From a26597619ea0d5d08f1653c01ffceece117b46d8 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:52:54 +0900 Subject: [PATCH 07/12] Apply suggestions from code review Co-authored-by: sator-imaging <16752340+sator-imaging@users.noreply.github.com> --- tests/ShapeTagEmissionTests.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ShapeTagEmissionTests.cs b/tests/ShapeTagEmissionTests.cs index 4669529..36d57d3 100644 --- a/tests/ShapeTagEmissionTests.cs +++ b/tests/ShapeTagEmissionTests.cs @@ -20,7 +20,7 @@ public void ShapeTagIsCommentedOutByDefault() string generatedView = GenerateView("[ZeroSerializer.ZeroSerializer] public class Record { public int Value { get; set; } }"); Assert.DoesNotContain("/// ", generatedView); - Assert.Contains("// To emit this, set EmitShapeTag = true on ZeroSerializerAttribute.", generatedView); + Assert.Contains("// To emit this, `set EmitShapeTag = true` on ZeroSerializerAttribute.", generatedView); Assert.Contains("// public const string ShapeTag = \"v1/{int}\";", generatedView); Assert.Contains("public const uint ShapeHash = ", generatedView); } @@ -34,6 +34,9 @@ public void ShapeTagAndRemarksAreEmittedWhenRequested() Assert.Contains("/// ShapeTag: v1/{int}", generatedView); Assert.Contains("public const string ShapeTag = \"v1/{int}\";", generatedView); Assert.DoesNotContain("// public const string ShapeTag", generatedView); + Assert.Contains("public const uint ShapeHash = ", generatedView); + + Assert.DoesNotContain(" public const string ShapeTag", generatedView); } [Fact] From 05ded50cceaaf8997476a59b095f415f6470aa9d Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:36:14 +0900 Subject: [PATCH 08/12] Apply suggestion from @sator-imaging --- tests/ShapeTagEmissionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ShapeTagEmissionTests.cs b/tests/ShapeTagEmissionTests.cs index 36d57d3..df396b4 100644 --- a/tests/ShapeTagEmissionTests.cs +++ b/tests/ShapeTagEmissionTests.cs @@ -23,6 +23,8 @@ public void ShapeTagIsCommentedOutByDefault() Assert.Contains("// To emit this, `set EmitShapeTag = true` on ZeroSerializerAttribute.", generatedView); Assert.Contains("// public const string ShapeTag = \"v1/{int}\";", generatedView); Assert.Contains("public const uint ShapeHash = ", generatedView); + + Assert.DoesNotContain(" public const string ShapeTag", generatedView); } [Fact] @@ -35,8 +37,6 @@ public void ShapeTagAndRemarksAreEmittedWhenRequested() Assert.Contains("public const string ShapeTag = \"v1/{int}\";", generatedView); Assert.DoesNotContain("// public const string ShapeTag", generatedView); Assert.Contains("public const uint ShapeHash = ", generatedView); - - Assert.DoesNotContain(" public const string ShapeTag", generatedView); } [Fact] From e63ae666d8d385dc93dacca4a493003dae8904fb Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:38:05 +0900 Subject: [PATCH 09/12] Apply suggestion from @sator-imaging --- tests/ShapeTagEmissionTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/ShapeTagEmissionTests.cs b/tests/ShapeTagEmissionTests.cs index df396b4..6d77403 100644 --- a/tests/ShapeTagEmissionTests.cs +++ b/tests/ShapeTagEmissionTests.cs @@ -19,11 +19,10 @@ public void ShapeTagIsCommentedOutByDefault() { string generatedView = GenerateView("[ZeroSerializer.ZeroSerializer] public class Record { public int Value { get; set; } }"); - Assert.DoesNotContain("/// ", generatedView); Assert.Contains("// To emit this, `set EmitShapeTag = true` on ZeroSerializerAttribute.", generatedView); Assert.Contains("// public const string ShapeTag = \"v1/{int}\";", generatedView); Assert.Contains("public const uint ShapeHash = ", generatedView); - + Assert.DoesNotContain("/// ", generatedView); Assert.DoesNotContain(" public const string ShapeTag", generatedView); } From d640c542396c7c39c2cfcff91351de82c94f5adc Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:38:54 +0900 Subject: [PATCH 10/12] Apply suggestion from @sator-imaging --- tests/ShapeTagEmissionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ShapeTagEmissionTests.cs b/tests/ShapeTagEmissionTests.cs index 6d77403..b4df27c 100644 --- a/tests/ShapeTagEmissionTests.cs +++ b/tests/ShapeTagEmissionTests.cs @@ -23,7 +23,7 @@ public void ShapeTagIsCommentedOutByDefault() Assert.Contains("// public const string ShapeTag = \"v1/{int}\";", generatedView); Assert.Contains("public const uint ShapeHash = ", generatedView); Assert.DoesNotContain("/// ", generatedView); - Assert.DoesNotContain(" public const string ShapeTag", generatedView); + Assert.DoesNotContain(" public const string ShapeTag", generatedView); } [Fact] From 5a2352cc2998c2f90e71776d4848055633d28048 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:48:52 +0900 Subject: [PATCH 11/12] Apply suggestion from @sator-imaging --- tests/ShapeTagEmissionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ShapeTagEmissionTests.cs b/tests/ShapeTagEmissionTests.cs index b4df27c..770b62d 100644 --- a/tests/ShapeTagEmissionTests.cs +++ b/tests/ShapeTagEmissionTests.cs @@ -19,11 +19,11 @@ public void ShapeTagIsCommentedOutByDefault() { string generatedView = GenerateView("[ZeroSerializer.ZeroSerializer] public class Record { public int Value { get; set; } }"); + Assert.DoesNotContain("/// ", generatedView); + Assert.DoesNotContain(" public const string ShapeTag", generatedView); Assert.Contains("// To emit this, `set EmitShapeTag = true` on ZeroSerializerAttribute.", generatedView); Assert.Contains("// public const string ShapeTag = \"v1/{int}\";", generatedView); Assert.Contains("public const uint ShapeHash = ", generatedView); - Assert.DoesNotContain("/// ", generatedView); - Assert.DoesNotContain(" public const string ShapeTag", generatedView); } [Fact] From 172c68201f468883b733079b4711fe55e16245a5 Mon Sep 17 00:00:00 2001 From: sator-imaging <16752340+sator-imaging@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:49:30 +0900 Subject: [PATCH 12/12] Apply suggestion from @sator-imaging --- tests/ShapeTagEmissionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ShapeTagEmissionTests.cs b/tests/ShapeTagEmissionTests.cs index 770b62d..02a4d38 100644 --- a/tests/ShapeTagEmissionTests.cs +++ b/tests/ShapeTagEmissionTests.cs @@ -31,10 +31,10 @@ public void ShapeTagAndRemarksAreEmittedWhenRequested() { string generatedView = GenerateView("[ZeroSerializer.ZeroSerializer(EmitShapeTag = true)] public class Record { public int Value { get; set; } }"); + Assert.DoesNotContain("// public const string ShapeTag", generatedView); Assert.Contains("/// ", generatedView); Assert.Contains("/// ShapeTag: v1/{int}", generatedView); Assert.Contains("public const string ShapeTag = \"v1/{int}\";", generatedView); - Assert.DoesNotContain("// public const string ShapeTag", generatedView); Assert.Contains("public const uint ShapeHash = ", generatedView); }