From af7c9491e45c79fab06d57c7c26e52c5e6b33586 Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Thu, 18 Dec 2025 09:23:41 +0100 Subject: [PATCH] DeviceDependentGenerator can now add suffix to the name of the generated types. --- .../DeviceDependentGeneratorTests.cs | 18 +++++----- .../DeviceDependentGenerator.cs | 35 +++++++++++++++---- .../DeviceDependentTemplateAttribute.cs | 6 ++-- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/DeviceDependentGenerator.Tests/DeviceDependentGeneratorTests.cs b/DeviceDependentGenerator.Tests/DeviceDependentGeneratorTests.cs index 74dadc8..e513434 100644 --- a/DeviceDependentGenerator.Tests/DeviceDependentGeneratorTests.cs +++ b/DeviceDependentGenerator.Tests/DeviceDependentGeneratorTests.cs @@ -9,7 +9,7 @@ namespace DeviceDependentGenerator.Tests; public sealed class DeviceDependentGeneratorTests { [Fact] - public void Generates_classes_per_enum_value_and_filters_device_blocks() + public void Generates_classes_per_enum_value_and_filters_device_blocks_with_suffix() { const string attributeAndEnum = """ using System; @@ -19,7 +19,7 @@ public sealed class DeviceDependentGeneratorTests [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] public sealed class DeviceDependentTemplateAttribute : Attribute { - public DeviceDependentTemplateAttribute(Type enumType) { } + public DeviceDependentTemplateAttribute(Type enumType, string? suffix = null) { } } public enum CalculationDevice @@ -35,7 +35,7 @@ public sealed class DeviceDependentGeneratorTests namespace PerfectNumbers.Core; - [DeviceDependentTemplate(typeof(CalculationDevice))] + [DeviceDependentTemplate(typeof(CalculationDevice), suffix: "Impl")] public static class PrimeCalculatorTemplate { #if DEVICE_CPU @@ -65,21 +65,21 @@ public sealed class DeviceDependentGeneratorTests ImmutableArray generated = runResult.Results.Single().GeneratedSources; - string cpu = generated.Single(s => s.HintName.EndsWith("PrimeCalculator.Cpu.generated.cs", StringComparison.Ordinal)).SourceText.ToString(); - string hybrid = generated.Single(s => s.HintName.EndsWith("PrimeCalculator.Hybrid.generated.cs", StringComparison.Ordinal)).SourceText.ToString(); - string gpu = generated.Single(s => s.HintName.EndsWith("PrimeCalculator.Gpu.generated.cs", StringComparison.Ordinal)).SourceText.ToString(); + string cpu = generated.Single(s => s.HintName.EndsWith("PrimeCalculator.CpuImpl.generated.cs", StringComparison.Ordinal)).SourceText.ToString(); + string hybrid = generated.Single(s => s.HintName.EndsWith("PrimeCalculator.HybridImpl.generated.cs", StringComparison.Ordinal)).SourceText.ToString(); + string gpu = generated.Single(s => s.HintName.EndsWith("PrimeCalculator.GpuImpl.generated.cs", StringComparison.Ordinal)).SourceText.ToString(); - cpu.Should().Contain("class PrimeCalculatorCpu"); + cpu.Should().Contain("class PrimeCalculatorCpuImpl"); cpu.Should().Contain("=> \"CPU\""); cpu.Should().NotContain("#if"); cpu.Should().NotContain("#endif"); - hybrid.Should().Contain("class PrimeCalculatorHybrid"); + hybrid.Should().Contain("class PrimeCalculatorHybridImpl"); hybrid.Should().Contain("=> \"HYBRID\""); hybrid.Should().NotContain("#if"); hybrid.Should().NotContain("#endif"); - gpu.Should().Contain("class PrimeCalculatorGpu"); + gpu.Should().Contain("class PrimeCalculatorGpuImpl"); gpu.Should().Contain("=> \"GPU\""); gpu.Should().NotContain("#if"); gpu.Should().NotContain("#endif"); diff --git a/DeviceDependentGenerator/DeviceDependentGenerator.cs b/DeviceDependentGenerator/DeviceDependentGenerator.cs index d2f4222..379fea4 100644 --- a/DeviceDependentGenerator/DeviceDependentGenerator.cs +++ b/DeviceDependentGenerator/DeviceDependentGenerator.cs @@ -75,7 +75,7 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator } AttributeData attributeData = attributeContext.Attributes[0]; - if (attributeData.ConstructorArguments.Length != 1) + if (attributeData.ConstructorArguments.Length is not (1 or 2)) { return null; } @@ -85,6 +85,23 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator return null; } + string? suffix = null; + if (attributeData.ConstructorArguments.Length == 2) + { + suffix = attributeData.ConstructorArguments[1].Value as string; + } + + if (suffix is null && attributeData.NamedArguments.Length != 0) + { + foreach (KeyValuePair namedArgument in attributeData.NamedArguments) + { + if (string.Equals(namedArgument.Key, "suffix", StringComparison.OrdinalIgnoreCase)) + { + suffix = namedArgument.Value.Value as string; + } + } + } + if (enumTypeSymbol.TypeKind != TypeKind.Enum) { Location location = attributeContext.TargetNode.GetLocation(); @@ -99,7 +116,7 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator .ToImmutableArray(); Location attributeLocation = attributeContext.TargetNode.GetLocation(); - return TemplateInfo.CreateValid(templateSymbol, enumTypeSymbol, attributeLocation, enumValues); + return TemplateInfo.CreateValid(templateSymbol, enumTypeSymbol, attributeLocation, enumValues, suffix); } private static void GenerateForTemplate(SourceProductionContext context, TemplateInfo template, GeneratorOptions options) @@ -149,7 +166,7 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator continue; } - string generatedTypeName = baseName + enumValueName; + string generatedTypeName = baseName + enumValueName + template.Suffix; TypeDeclarationSyntax generatedTypeSyntax = TransformTemplateType(deviceTemplateSyntax, generatedTypeName); CompilationUnitSyntax generatedRoot = BuildGeneratedFile( @@ -161,7 +178,7 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator generatedRoot = (CompilationUnitSyntax)new ConditionalDirectiveAndDisabledTextStripper().Visit(generatedRoot)!; generatedRoot = generatedRoot.NormalizeWhitespace(); - string generatedFileName = baseName + "." + enumValueName + ".generated.cs"; + string generatedFileName = baseName + "." + enumValueName + template.Suffix + ".generated.cs"; string hintName = options.BuildHintName(filePath, generatedFileName); context.AddSource( hintName, @@ -280,12 +297,14 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator INamedTypeSymbol enumType, Location attributeLocation, ImmutableArray enumValues, + string? suffix, bool valid) { TemplateType = templateType; EnumType = enumType; AttributeLocation = attributeLocation; EnumValues = enumValues; + Suffix = suffix ?? string.Empty; Valid = valid; } @@ -293,6 +312,7 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator public INamedTypeSymbol EnumType { get; } public Location AttributeLocation { get; } public ImmutableArray EnumValues { get; } + public string Suffix { get; } public bool Valid { get; } public string Name => TemplateType.Name; @@ -304,14 +324,15 @@ public sealed class DeviceDependentGenerator : IIncrementalGenerator public SyntaxReference? DeclaringSyntaxReference => TemplateType.DeclaringSyntaxReferences.FirstOrDefault(); public static TemplateInfo CreateInvalidEnum(INamedTypeSymbol templateType, INamedTypeSymbol enumType, Location attributeLocation) - => new(templateType, enumType, attributeLocation, enumValues: default, valid: false); + => new(templateType, enumType, attributeLocation, enumValues: default, suffix: null, valid: false); public static TemplateInfo CreateValid( INamedTypeSymbol templateType, INamedTypeSymbol enumType, Location attributeLocation, - ImmutableArray enumValues) - => new(templateType, enumType, attributeLocation, enumValues, valid: true); + ImmutableArray enumValues, + string? suffix) + => new(templateType, enumType, attributeLocation, enumValues, suffix, valid: true); } private readonly struct GeneratorOptions diff --git a/PerfectNumbers.Core/DeviceDependentTemplateAttribute.cs b/PerfectNumbers.Core/DeviceDependentTemplateAttribute.cs index 5a6b63e..291fb4f 100644 --- a/PerfectNumbers.Core/DeviceDependentTemplateAttribute.cs +++ b/PerfectNumbers.Core/DeviceDependentTemplateAttribute.cs @@ -5,11 +5,13 @@ namespace PerfectNumbers.Core; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] public sealed class DeviceDependentTemplateAttribute : Attribute { - public DeviceDependentTemplateAttribute(Type enumType) + public DeviceDependentTemplateAttribute(Type enumType, string? suffix = null) { EnumType = enumType ?? throw new ArgumentNullException(nameof(enumType)); + Suffix = suffix; } public Type EnumType { get; } -} + public string? Suffix { get; } +}