DeviceDependentGenerator can now add suffix to the name of the generated types.

This commit is contained in:
mlemanczyk committed 2025-12-18 09:23:41 +01:00
1 parent 0b226c76e8
commit af7c9491e4
3 files changed
+41 -18

No files matched your search

@@ -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<GeneratedSourceResult> 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");
@@ -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<string, TypedConstant> 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<string> 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<string> 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<string> enumValues)
=> new(templateType, enumType, attributeLocation, enumValues, valid: true);
ImmutableArray<string> enumValues,
string? suffix)
=> new(templateType, enumType, attributeLocation, enumValues, suffix, valid: true);
}
private readonly struct GeneratorOptions
@@ -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; }
}