Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Optify.Tests/DebugGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public Task Should_allow_the_debugger_in_the_generator()
var compilation = CSharpCompilation
.Create("CSharpCodeGen.GenerateAssembly")
.AddSyntaxTrees(CSharpSyntaxTree.ParseText(DebugGeneratorSource.Source))
.AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
.AddReferences(
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(OptifyOptionsAttribute).Assembly.Location)
)
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var driver = CSharpGeneratorDriver
.Create(generator)
Expand All @@ -30,7 +33,8 @@ file static class DebugGeneratorSource
using Optify;
namespace CSharpCodeGen;

[OptifyOptions] public class Config;
[OptifyOptions]
public class Config;

[OptifyOptions(SectionName = "OverrideNamedDummySettings")]
public class NamedDummySettings;
Expand Down
21 changes: 7 additions & 14 deletions Optify/OptifyGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
if (ctx.TargetSymbol is not INamedTypeSymbol target)
return new OptionsTypeToRegister();

var fullName = target.ToDisplayString(
SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle(
SymbolDisplayGlobalNamespaceStyle.Omitted
)
);
var sectionNameArg = ctx.Attributes[0]
.NamedArguments.FirstOrDefault(static x => x.Key == nameof(OptifyOptionsAttribute.SectionName));
var sectionName = sectionNameArg.Value.Value as string ?? ctx.TargetSymbol.Name;
var validationArg = ctx.Attributes[0]
.NamedArguments.FirstOrDefault(static x => x.Key == nameof(OptifyOptionsAttribute.Validation));
var validation = validationArg.Value.Value is int v ? v : 0;

return new OptionsTypeToRegister(sectionName, fullName, (ValidationFlag)validation);
// At this point, ctx.Attributes *only* contains OptifyOptionsAttribute, even
// when other attributes are on the type. A user should receive a compiler error
// CS0579 if they added more than one [OptifyOptions]. However, generated source
// may be able to bypass that. In such a case, we're just going to assume
// that we'll take the first one.
return new OptionsTypeToRegister(ctx.Attributes[0], target);
}
);

context.RegisterSourceOutput(
provider.Where(static opt => !opt.IsNull).Collect(),
provider.Where(static opt => opt.IsValid).Collect(),
static (spc, types) =>
{
spc.AddSource(OptifyRegistrationSource.Filename, OptifyRegistrationSource.GenerateSource(types));
Expand Down
33 changes: 24 additions & 9 deletions Optify/OptionsTypeToRegister.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
using Microsoft.CodeAnalysis;

namespace Optify;

public readonly record struct OptionsTypeToRegister
{
public readonly bool IsNull;
public readonly string SectionName = string.Empty;
public readonly string FullName = string.Empty;
public readonly ValidationFlag Validation = 0;
public bool IsValid { get; }
public string SectionName { get; } = string.Empty;
public string FullName { get; } = string.Empty;
public ValidationFlag Validation { get; }

public OptionsTypeToRegister(string sectionName, string fullName, ValidationFlag validation)
public OptionsTypeToRegister(AttributeData attributeData, INamedTypeSymbol targetType)
{
SectionName = sectionName;
FullName = fullName;
Validation = validation;
FullName = targetType.ToDisplayString();
SectionName = targetType.Name;
IsValid = true;

foreach (var argument in attributeData.NamedArguments)
{
switch (argument.Key)
{
case nameof(OptifyOptionsAttribute.SectionName):
SectionName = argument.Value.Value as string ?? targetType.Name;
break;
case nameof(OptifyOptionsAttribute.Validation):
Validation = argument.Value.Value is int intValue ? (ValidationFlag)intValue : 0;
break;
}
}
}

public OptionsTypeToRegister()
{
IsNull = true;
IsValid = false;
}
}