diff --git a/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterEndpointAttribute.cs b/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterEndpointAttribute.cs
new file mode 100644
index 0000000..7ee97ff
--- /dev/null
+++ b/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterEndpointAttribute.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Net.Http;
+
+namespace AStar.Dev.Source.Generators.Attributes;
+
+///
+/// An attribute to automatically register a minimal APU endpoint.
+///
+///
+/// This attribute is used to mark classes for automatic endpoint registration in the system.
+/// It supports specifying an HTTP method type and an optional method group name for categorization or grouping.
+///
+[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+public class AutoRegisterEndpointAttribute(HttpMethod? methodType, string? methodGroupName = null) : Attribute
+{
+ ///
+ /// Gets the HTTP method type associated with the endpoint.
+ ///
+ ///
+ /// If no specific HTTP method is provided during initialization, the default value is .
+ ///
+ ///
+ /// Represents the HTTP method used for the endpoint, as an instance of the class.
+ ///
+ public HttpMethod MethodType { get; } = methodType ?? HttpMethod.Get;
+
+ ///
+ /// Gets the group name associated with the method for organizational purposes.
+ ///
+ ///
+ /// This property provides a way to categorize or group methods logically within a larger structure.
+ /// If no group name is specified during initialization, the value will be .
+ ///
+ ///
+ /// Represents the name of the method group as a . Can be if not explicitly set.
+ ///
+ public string? MethodGroupName { get; } = methodGroupName;
+}
diff --git a/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterOptions.cs b/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterOptions.cs
index 71a0847..1bbf91b 100644
--- a/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterOptions.cs
+++ b/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterOptions.cs
@@ -2,6 +2,14 @@
namespace AStar.Dev.Source.Generators.Attributes;
+///
+/// Attribute used to indicate that a class or struct should be automatically registered as an ,
+/// with an optional section name provided for configuration purposes.
+///
+///
+/// This attribute can only be applied to classes or structs. It is not inherited by derived types
+/// and does not allow multiple usage on the same target.
+///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
public class AutoRegisterOptionsAttribute(string? sectionName = null) : Attribute
{
diff --git a/src/AStar.Dev.Source.Generators.Attributes/ServiceAttribute.cs b/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterServiceAttribute.cs
similarity index 86%
rename from src/AStar.Dev.Source.Generators.Attributes/ServiceAttribute.cs
rename to src/AStar.Dev.Source.Generators.Attributes/AutoRegisterServiceAttribute.cs
index 45f1ef9..46d74e1 100644
--- a/src/AStar.Dev.Source.Generators.Attributes/ServiceAttribute.cs
+++ b/src/AStar.Dev.Source.Generators.Attributes/AutoRegisterServiceAttribute.cs
@@ -3,7 +3,7 @@
namespace AStar.Dev.Source.Generators.Attributes;
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
-public sealed class ServiceAttribute(ServiceLifetime lifetime = ServiceLifetime.Scoped) : Attribute
+public sealed class AutoRegisterServiceAttribute(ServiceLifetime lifetime = ServiceLifetime.Scoped) : Attribute
{
///
/// Specifies the lifetime of the service. Defaults to Scoped.
diff --git a/src/AStar.Dev.Source.Generators.Attributes/ServiceLifetime.cs b/src/AStar.Dev.Source.Generators.Attributes/ServiceLifetime.cs
index 0aaf428..bbf8ca2 100644
--- a/src/AStar.Dev.Source.Generators.Attributes/ServiceLifetime.cs
+++ b/src/AStar.Dev.Source.Generators.Attributes/ServiceLifetime.cs
@@ -1,3 +1,6 @@
namespace AStar.Dev.Source.Generators.Attributes;
+///
+/// Specifies the lifetime of a service within a dependency injection container.
+///
public enum ServiceLifetime { Singleton, Scoped, Transient }
diff --git a/src/AStar.Dev.Source.Generators/AStar.Dev.Source.Generators.csproj b/src/AStar.Dev.Source.Generators/AStar.Dev.Source.Generators.csproj
index b8edbd0..d0c53f2 100644
--- a/src/AStar.Dev.Source.Generators/AStar.Dev.Source.Generators.csproj
+++ b/src/AStar.Dev.Source.Generators/AStar.Dev.Source.Generators.csproj
@@ -9,26 +9,29 @@
true
true
AStar.Dev.Source.Generators
-
false
true
-
false
$(NoWarn);NU5128
- 0.1.3
- AStar Dev
- AStar
+ 0.1.4
+ AStar Development, Jason Barden
+ AStar Development
Source generators and supporting attribute types for AStar.Dev projects.
source-generator;strongid;attributes;astartools
- https://example.com/AStar.Dev.Source.Generators
- https://github.com/your-org/SourceGenerators1111
+ https://astardevelopment.co.uk
+ https://github.com/astar-development/astar-dev-source-generators.git
git
MIT
false
- Initial 0.1.2 release.
+ v0.1.4 - Add missing namespace in generated ServiceRegistrations class.
+- Rename ServiceAttribute to AutoRegisterServiceAttribute for clarity
main
+ AStar Dev Source Generators
+ Readme.md
+ astar.png
+ True
@@ -59,7 +62,18 @@
-
-
+
+
+
+
+
+ True
+ \
+
+
+ True
+ \
+
+
diff --git a/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionBindingGenerator.cs b/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionBindingGenerator.cs
index d77f728..d37dc96 100644
--- a/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionBindingGenerator.cs
+++ b/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionBindingGenerator.cs
@@ -61,7 +61,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var fullTypeName = ns != null ? string.Concat(ns, ".", typeName) : typeName;
string? sectionName = null;
AttributeData? attr = typeSymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass?.ToDisplayString() == AttrFqn);
- if(attr != null && attr.ConstructorArguments.Length > 0 && attr.ConstructorArguments[0].Value is string s && !string.IsNullOrWhiteSpace(s))
+ if(attr is { ConstructorArguments.Length: > 0 } && attr.ConstructorArguments[0].Value is string s && !string.IsNullOrWhiteSpace(s))
{
sectionName = s;
}
@@ -72,23 +72,27 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
if(attrSyntax?.ArgumentList?.Arguments.Count > 0)
{
ExpressionSyntax expr = attrSyntax.ArgumentList.Arguments[0].Expression;
- if(expr is LiteralExpressionSyntax literal && literal.Token.Value is string literalValue)
- {
- sectionName = literalValue;
- }
+ if(expr is LiteralExpressionSyntax { Token.Value: string literalValue }) sectionName = literalValue;
}
}
- if(string.IsNullOrWhiteSpace(sectionName))
+ return !string.IsNullOrWhiteSpace(sectionName)
+ ? new OptionsTypeInfo(typeName, fullTypeName, sectionName!, ctx.TargetNode.GetLocation())
+ : ExtractSectionNameFromMembers(ctx, typeSymbol, sectionName, typeName, fullTypeName);
+ }
+
+ private static OptionsTypeInfo? ExtractSectionNameFromMembers(GeneratorAttributeSyntaxContext ctx, INamedTypeSymbol typeSymbol, string? sectionName, string typeName, string fullTypeName)
+ {
+ foreach(ISymbol member in typeSymbol.GetMembers())
{
- foreach(ISymbol member in typeSymbol.GetMembers())
+ if(member is not IFieldSymbol { IsStatic: true, IsConst: true, Name: "SectionName" } field || field.Type.SpecialType != SpecialType.System_String ||
+ field.ConstantValue is not string val || string.IsNullOrWhiteSpace(val))
{
- if(member is IFieldSymbol field && field.IsStatic && field.IsConst && field.Name == "SectionName" && field.Type.SpecialType == SpecialType.System_String && field.ConstantValue is string val && !string.IsNullOrWhiteSpace(val))
- {
- sectionName = val;
- break;
- }
+ continue;
}
+
+ sectionName = val;
+ break;
}
return new OptionsTypeInfo(typeName, fullTypeName, sectionName ?? string.Empty, ctx.TargetNode.GetLocation());
diff --git a/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionsBindingCodeGenerator.cs b/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionsBindingCodeGenerator.cs
index 1c0655b..20b4029 100644
--- a/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionsBindingCodeGenerator.cs
+++ b/src/AStar.Dev.Source.Generators/OptionsBindingGeneration/OptionsBindingCodeGenerator.cs
@@ -18,10 +18,7 @@ public static string Generate(IReadOnlyList types)
_ = sb.AppendLine(" {");
_ = sb.AppendLine(" public static IServiceCollection AddAutoRegisteredOptions(this IServiceCollection services, IConfiguration configuration)");
_ = sb.AppendLine(" {");
- foreach(OptionsTypeInfo info in types)
- {
- _ = sb.AppendLine($" services.AddOptions<{info.FullTypeName}>()\n .Bind(configuration.GetSection(\"{EscapeString(info.SectionName)}\"))\n .ValidateDataAnnotations()\n .ValidateOnStart();");
- }
+ foreach(OptionsTypeInfo info in types) _ = sb.AppendLine($" services.AddOptions<{info.FullTypeName}>()\n .Bind(configuration.GetSection(\"{EscapeString(info.SectionName)}\"))\n .ValidateDataAnnotations()\n .ValidateOnStart();");
_ = sb.AppendLine(" return services;");
_ = sb.AppendLine(" }");
@@ -30,5 +27,5 @@ public static string Generate(IReadOnlyList types)
return sb.ToString();
}
- private static string EscapeString(string s) => s?.Replace("\\", "\\\\").Replace("\"", "\\\"") ?? string.Empty;
+ private static string EscapeString(string s) => s?.Replace("\\", @"\\").Replace("\"", "\\\"") ?? string.Empty;
}
diff --git a/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceCollectionCodeGenerator.cs b/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceCollectionCodeGenerator.cs
index 8ae22ab..e84e74e 100644
--- a/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceCollectionCodeGenerator.cs
+++ b/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceCollectionCodeGenerator.cs
@@ -2,31 +2,31 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using AStar.Dev.Source.Generators.Attributes;
namespace AStar.Dev.Source.Generators.ServiceRegistrationGeneration;
internal static class ServiceCollectionCodeGenerator
{
- public static string Generate(IReadOnlyList items)
+ public static string Generate(IReadOnlyList items)
{
IEnumerable registrations = BuildServiceRegistrations(items);
- return BuildSourceFile(registrations);
+ ServiceModel? item = items.FirstOrDefault();
+ return BuildSourceFile(registrations, item?.Namespace ?? "AStar.Dev");
}
- private static IEnumerable BuildServiceRegistrations(IReadOnlyList items)
+ private static IEnumerable BuildServiceRegistrations(IReadOnlyList items)
{
var seen = new HashSet(StringComparer.Ordinal);
- foreach(ServiceRegistrationGenerator.ServiceModel model in items)
+ foreach(ServiceModel model in items)
{
foreach(var registration in CreateRegistrationsForModel(model).Where(seen.Add))
- {
yield return registration;
- }
}
}
- private static IEnumerable CreateRegistrationsForModel(ServiceRegistrationGenerator.ServiceModel model)
+ private static IEnumerable CreateRegistrationsForModel(ServiceModel model)
{
var method = GetRegistrationMethod(model.Lifetime);
@@ -43,20 +43,23 @@ private static IEnumerable CreateRegistrationsForModel(ServiceRegistrati
}
}
- private static string GetRegistrationMethod(ServiceRegistrationGenerator.Lifetime lifetime) => lifetime switch
- {
- ServiceRegistrationGenerator.Lifetime.Singleton => "AddSingleton",
- ServiceRegistrationGenerator.Lifetime.Scoped => "AddScoped",
- ServiceRegistrationGenerator.Lifetime.Transient => "AddTransient",
- _ => "AddScoped"
- };
+ private static string GetRegistrationMethod(ServiceLifetime lifetime)
+ => lifetime switch
+ {
+ ServiceLifetime.Singleton => "AddSingleton",
+ ServiceLifetime.Scoped => "AddScoped",
+ ServiceLifetime.Transient => "AddTransient",
+ _ => "AddScoped"
+ };
- private static string BuildSourceFile(IEnumerable registrations)
+ private static string BuildSourceFile(IEnumerable registrations, string @namespace)
{
var sb = new StringBuilder();
_ = sb.AppendLine("// ");
_ = sb.AppendLine("using Microsoft.Extensions.DependencyInjection;");
_ = sb.AppendLine();
+ _ = sb.AppendLine($"namespace {@namespace};");
+ _ = sb.AppendLine();
_ = sb.AppendLine("public static class GeneratedServiceCollectionExtensions");
_ = sb.AppendLine("{");
_ = sb.AppendLine(" public static IServiceCollection AddAnnotatedServices(this IServiceCollection s)");
diff --git a/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceModel.cs b/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceModel.cs
new file mode 100644
index 0000000..52030f7
--- /dev/null
+++ b/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceModel.cs
@@ -0,0 +1,81 @@
+using System.Collections.Generic;
+using System.Linq;
+using AStar.Dev.Source.Generators.Attributes;
+using Microsoft.CodeAnalysis;
+
+namespace AStar.Dev.Source.Generators.ServiceRegistrationGeneration;
+
+internal sealed class ServiceModel(ServiceLifetime lifetime, string implFqn, string? serviceFqn, bool alsoAsSelf, string @namespace)
+{
+ public ServiceLifetime Lifetime { get; } = lifetime;
+ public string ImplFqn { get; } = implFqn;
+ public string? ServiceFqn { get; } = serviceFqn;
+ public string? Namespace { get; } = @namespace;
+ public bool AlsoAsSelf { get; } = alsoAsSelf;
+
+ public static ServiceModel? TryCreate(INamedTypeSymbol impl, AttributeData attr)
+ {
+ if(!IsValidImplementationType(impl))
+ return null;
+
+ ServiceLifetime lifetime = ExtractLifetime(attr);
+ INamedTypeSymbol? asType = ExtractAsType(attr);
+ var asSelf = ExtractAsSelf(attr);
+ INamedTypeSymbol? service = asType ?? InferServiceType(impl);
+ var ns = impl.ContainingNamespace.IsGlobalNamespace ? null : impl.ContainingNamespace.ToDisplayString();
+
+ // Only skip if no service and not alsoAsSelf
+ return service is null && !asSelf
+ ? null
+ : new ServiceModel(
+ lifetime: lifetime,
+ implFqn: impl.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
+ serviceFqn: service?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
+ alsoAsSelf: asSelf,
+ @namespace: ns
+ );
+ }
+
+ private static bool IsValidImplementationType(INamedTypeSymbol impl) => !impl.IsAbstract &&
+ impl.Arity == 0 &&
+ impl.DeclaredAccessibility == Accessibility.Public;
+
+ private static ServiceLifetime ExtractLifetime(AttributeData attr) => attr.ConstructorArguments.Length == 1 &&
+ attr.ConstructorArguments[0].Value is int li
+ ? (ServiceLifetime)li
+ : ServiceLifetime.Scoped;
+
+ private static INamedTypeSymbol? ExtractAsType(AttributeData attr)
+ {
+ foreach(KeyValuePair na in attr.NamedArguments)
+ {
+ if(na.Key == "As" && na.Value.Value is INamedTypeSymbol ts)
+ return ts;
+ }
+
+ return null;
+ }
+
+ private static bool ExtractAsSelf(AttributeData attr)
+ {
+ foreach(KeyValuePair na in attr.NamedArguments)
+ {
+ if(na.Key == "AsSelf" && na.Value.Value is bool b)
+ return b;
+ }
+
+ return false;
+ }
+
+ private static INamedTypeSymbol? InferServiceType(INamedTypeSymbol impl)
+ {
+ INamedTypeSymbol[] candidates = [.. impl.AllInterfaces.Where(IsEligibleServiceInterface)];
+
+ return candidates.Length == 1 ? candidates[0] : null;
+ }
+
+ private static bool IsEligibleServiceInterface(INamedTypeSymbol i) => i.DeclaredAccessibility == Accessibility.Public &&
+ i.TypeKind == TypeKind.Interface &&
+ i.Arity == 0 &&
+ i.ToDisplayString() != "System.IDisposable";
+}
diff --git a/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceRegistrationGenerator.cs b/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceRegistrationGenerator.cs
index 13ad9a5..3aeecaa 100644
--- a/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceRegistrationGenerator.cs
+++ b/src/AStar.Dev.Source.Generators/ServiceRegistrationGeneration/ServiceRegistrationGenerator.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using System.Collections.Immutable;
+using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -9,7 +8,7 @@ namespace AStar.Dev.Source.Generators.ServiceRegistrationGeneration;
[Generator]
[System.Diagnostics.CodeAnalysis.SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1038:Compiler extensions should be implemented in assemblies with compiler-provided references", Justification = "")]
-public sealed class ServiceRegistrationGenerator : IIncrementalGenerator
+public sealed partial class ServiceRegistrationGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
@@ -27,7 +26,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
transform: static (syntaxCtx, _) => GetDeclaredSymbol(syntaxCtx))
.Where(static s => s is not null)!;
- private static bool IsClassCandidateForServiceRegistration(SyntaxNode node) => node is ClassDeclarationSyntax c &&
+ private static bool IsClassCandidateForServiceRegistration(SyntaxNode node)
+ => node is ClassDeclarationSyntax c &&
c.AttributeLists.Count > 0 &&
c.TypeParameterList is null;
@@ -42,7 +42,8 @@ private static bool IsClassCandidateForServiceRegistration(SyntaxNode node) => n
.Select(static (sym, _) => (sym, attr: FindServiceAttribute(sym!)))
.Where(static t => t.attr is not null)!;
- private static AttributeData? FindServiceAttribute(INamedTypeSymbol symbol) => symbol.GetAttributes()
+ private static AttributeData? FindServiceAttribute(INamedTypeSymbol symbol)
+ => symbol.GetAttributes()
.FirstOrDefault(a =>
a.AttributeClass?.Name == "ServiceAttribute" ||
a.AttributeClass?.ToDisplayString().EndsWith(".ServiceAttribute") == true);
@@ -52,85 +53,9 @@ private static bool IsClassCandidateForServiceRegistration(SyntaxNode node) => n
.Select(static (t, _) => ServiceModel.TryCreate(t.sym, t.attr!))
.Where(static m => m is not null)!;
- private static void GenerateSource(
- SourceProductionContext spc,
- (Compilation Left, ImmutableArray Right) pair)
+ private static void GenerateSource(SourceProductionContext spc, (Compilation Left, ImmutableArray Right) pair)
{
var code = ServiceCollectionCodeGenerator.Generate(pair.Right);
spc.AddSource("GeneratedServiceCollectionExtensions.g.cs", code);
}
-
- internal enum Lifetime { Singleton = 0, Scoped = 1, Transient = 2 }
-
- internal sealed class ServiceModel(ServiceRegistrationGenerator.Lifetime lifetime, string implFqn, string? serviceFqn, bool alsoAsSelf)
- {
- public Lifetime Lifetime { get; } = lifetime;
- public string ImplFqn { get; } = implFqn;
- public string? ServiceFqn { get; } = serviceFqn;
- public bool AlsoAsSelf { get; } = alsoAsSelf;
-
- public static ServiceModel? TryCreate(INamedTypeSymbol impl, AttributeData attr)
- {
- if(!IsValidImplementationType(impl))
- return null;
-
- Lifetime lifetime = ExtractLifetime(attr);
- INamedTypeSymbol? asType = ExtractAsType(attr);
- var asSelf = ExtractAsSelf(attr);
- INamedTypeSymbol? service = asType ?? InferServiceType(impl);
-
- // Only skip if no service and not alsoAsSelf
- return service is null && !asSelf
- ? null
- : new ServiceModel(
- lifetime: lifetime,
- implFqn: impl.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
- serviceFqn: service?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
- alsoAsSelf: asSelf
- );
- }
-
- private static bool IsValidImplementationType(INamedTypeSymbol impl) => !impl.IsAbstract &&
- impl.Arity == 0 &&
- impl.DeclaredAccessibility == Accessibility.Public;
-
- private static Lifetime ExtractLifetime(AttributeData attr) => attr.ConstructorArguments.Length == 1 &&
- attr.ConstructorArguments[0].Value is int li
- ? (Lifetime)li
- : Lifetime.Scoped;
-
- private static INamedTypeSymbol? ExtractAsType(AttributeData attr)
- {
- foreach(KeyValuePair na in attr.NamedArguments)
- {
- if(na.Key == "As" && na.Value.Value is INamedTypeSymbol ts)
- return ts;
- }
-
- return null;
- }
-
- private static bool ExtractAsSelf(AttributeData attr)
- {
- foreach(KeyValuePair na in attr.NamedArguments)
- {
- if(na.Key == "AsSelf" && na.Value.Value is bool b)
- return b;
- }
-
- return false;
- }
-
- private static INamedTypeSymbol? InferServiceType(INamedTypeSymbol impl)
- {
- INamedTypeSymbol[] candidates = [.. impl.AllInterfaces.Where(IsEligibleServiceInterface)];
-
- return candidates.Length == 1 ? candidates[0] : null;
- }
-
- private static bool IsEligibleServiceInterface(INamedTypeSymbol i) => i.DeclaredAccessibility == Accessibility.Public &&
- i.TypeKind == TypeKind.Interface &&
- i.Arity == 0 &&
- i.ToDisplayString() != "System.IDisposable";
- }
}
diff --git a/src/AStar.Dev.Source.Generators/astar.png b/src/AStar.Dev.Source.Generators/astar.png
new file mode 100644
index 0000000..74b197e
Binary files /dev/null and b/src/AStar.Dev.Source.Generators/astar.png differ
diff --git a/test/AStar.Dev.Source.Generators.Attributes.Tests.Unit/RegisterServiceAttributeShould.cs b/test/AStar.Dev.Source.Generators.Attributes.Tests.Unit/RegisterServiceAttributeShould.cs
new file mode 100644
index 0000000..284d635
--- /dev/null
+++ b/test/AStar.Dev.Source.Generators.Attributes.Tests.Unit/RegisterServiceAttributeShould.cs
@@ -0,0 +1,35 @@
+namespace AStar.Dev.Source.Generators.Attributes.Tests.Unit;
+
+public class RegisterServiceAttributeShould
+{
+ [Fact]
+ public void HaveDefaultLifetimeAsScoped()
+ => new AutoRegisterServiceAttribute().Lifetime.ShouldBe(ServiceLifetime.Scoped);
+
+ [Fact]
+ public void AllowSettingLifetimeViaConstructor()
+ => new AutoRegisterServiceAttribute(ServiceLifetime.Singleton).Lifetime.ShouldBe(ServiceLifetime.Singleton);
+
+ [Fact]
+ public void AllowSettingAsProperty()
+ => new AutoRegisterServiceAttribute { As = typeof(string) }.As.ShouldBe(typeof(string));
+
+ [Fact]
+ public void AllowSettingAsSelfProperty()
+ => new AutoRegisterServiceAttribute { AsSelf = true }.AsSelf.ShouldBeTrue();
+
+ [Fact]
+ public void BeApplicableToClassesOnly()
+ => typeof(AutoRegisterServiceAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
+ .OfType().Single().ValidOn.ShouldBe(AttributeTargets.Class);
+
+ [Fact]
+ public void NotBeInherited()
+ => typeof(AutoRegisterServiceAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
+ .OfType().Single().Inherited.ShouldBeFalse();
+
+ [Fact]
+ public void NotAllowMultipleUsageOnSameClass()
+ => typeof(AutoRegisterServiceAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
+ .OfType().Single().AllowMultiple.ShouldBeFalse();
+}
diff --git a/test/AStar.Dev.Source.Generators.Attributes.Tests.Unit/ServiceAttributeShould.cs b/test/AStar.Dev.Source.Generators.Attributes.Tests.Unit/ServiceAttributeShould.cs
deleted file mode 100644
index e03c4ff..0000000
--- a/test/AStar.Dev.Source.Generators.Attributes.Tests.Unit/ServiceAttributeShould.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-namespace AStar.Dev.Source.Generators.Attributes.Tests.Unit;
-
-public class ServiceAttributeShould
-{
- [Fact]
- public void HaveDefaultLifetimeAsScoped()
- => new ServiceAttribute().Lifetime.ShouldBe(ServiceLifetime.Scoped);
-
- [Fact]
- public void AllowSettingLifetimeViaConstructor()
- => new ServiceAttribute(ServiceLifetime.Singleton).Lifetime.ShouldBe(ServiceLifetime.Singleton);
-
- [Fact]
- public void AllowSettingAsProperty()
- => new ServiceAttribute { As = typeof(string) }.As.ShouldBe(typeof(string));
-
- [Fact]
- public void AllowSettingAsSelfProperty()
- => new ServiceAttribute { AsSelf = true }.AsSelf.ShouldBeTrue();
-
- [Fact]
- public void BeApplicableToClassesOnly()
- => typeof(ServiceAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
- .OfType().Single().ValidOn.ShouldBe(AttributeTargets.Class);
-
- [Fact]
- public void NotBeInherited()
- => typeof(ServiceAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
- .OfType().Single().Inherited.ShouldBeFalse();
-
- [Fact]
- public void NotAllowMultipleUsageOnSameClass()
- => typeof(ServiceAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
- .OfType().Single().AllowMultiple.ShouldBeFalse();
-}
diff --git a/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/StrongIdGeneratorTests.StrongId_GeneratesExpectedCode#OrderId.StrongId.g.received.cs b/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/StrongIdGeneratorTests.StrongId_GeneratesExpectedCode#OrderId.StrongId.g.received.cs
index e3d3fea..db6aef9 100644
--- a/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/StrongIdGeneratorTests.StrongId_GeneratesExpectedCode#OrderId.StrongId.g.received.cs
+++ b/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/StrongIdGeneratorTests.StrongId_GeneratesExpectedCode#OrderId.StrongId.g.received.cs
@@ -1,6 +1,10 @@
//HintName: OrderId.StrongId.g.cs
//
#nullable enable
+using System;
+
+namespace AStar.Dev.Source.Generators.Tests.Unit.StrongIdCodeGeneration;
+
public readonly partial struct OrderId : System.IEquatable
{
private readonly System.Guid _value;
@@ -18,7 +22,7 @@
public static bool TryParse(string? s, out OrderId value)
{
- var ok = System.Guid.TryParse(s, out var g);
+ var ok = System.Guid.TryParse(s, out Guid g);
value = ok ? new(g) : default;
return ok;
}
diff --git a/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/TestStrongIds.cs b/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/TestStrongIds.cs
index 1bf06cf..f6ef0bf 100644
--- a/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/TestStrongIds.cs
+++ b/test/AStar.Dev.Source.Generators.Tests.Unit/StrongIdCodeGeneration/TestStrongIds.cs
@@ -7,7 +7,7 @@ namespace AStar.Dev.Source.Generators.Tests.Unit.StrongIdCodeGeneration;
public readonly partial record struct UserId;
[StrongId(typeof(int))]
-public readonly partial record struct OrderId;
+public readonly partial record struct OrderId2;
[StrongId(typeof(System.Guid))]
public readonly partial record struct EntityId;