Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ Refactor the selected legacy emitter implementation from manual `string` / `Stri
### Requirements

1. Use structured declaration APIs where applicable:
- `WriteClass/WriteStruct/WriteRecordClass/WriteInterface/WriteEnum`
- `WriteMethod`, `WriteProperty`, `WriteField`, `WriteConstructor`
- `Class/Struct/RecordClass/Interface/Enum`
- `Method`, `Property`, `Field`, `Constructor`
2. Use XML helper extensions instead of raw `///` composition:
- `XmlSummary`, `XmlParam`, `XmlReturn`, `XmlRemarks`, `XmlCode` or `XmlCodeBlock`
3. Use `TypeReferenceOptions` when type text becomes complex (nullability, generics, arrays).
3. Use `TypeReference` when type text becomes complex (nullability, generics, arrays).
4. Ensure writer lifetime is output-scoped (`generationContext.CreateCodeWriter()` inside callback).
5. Preserve behavior, diagnostics, and generated names.
6. Keep changes minimal and focused; do not reformat unrelated logic.
Expand Down
114 changes: 0 additions & 114 deletions .agents/skills/project-placement-defaults/SKILL.md

This file was deleted.

2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<TUnitVersion>1.65.63</TUnitVersion>
<PurviewSourceGeneratorFrameworkVersion>1.0.0-prerelease.31</PurviewSourceGeneratorFrameworkVersion>
<PurviewSourceGeneratorFrameworkVersion>1.0.0-prerelease.35</PurviewSourceGeneratorFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.9.0" />
Expand Down
24 changes: 10 additions & 14 deletions src/src/SourceGeneration/Helpers/CodeGenEmiiter.ExtensionMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static void EmitExtensionClass(OutputContext context, CancellationToken cancella

context.Debug($"Generating extension class for host kit: {context.HostKit.HostKitType.Name}");

using (context.Writer.WriteBlockNamespaceScope(TypeLibrary.IDistributedApplicationBuilder))
using (context.Writer.BlockNamespaceScope(TypeLibrary.IDistributedApplicationBuilder))
{
AttributeDeclarationOptions editorBrowsable = new(TypeLibrary.EditorBrowsableAttribute)
{
Expand All @@ -19,7 +19,7 @@ static void EmitExtensionClass(OutputContext context, CancellationToken cancella

context
.Writer.XmlSummary($"Extension methods for {CodeWriter.XmlSee(context.HostKit.HostKitType)}.")
.WriteClass(
.Class(
new($"{context.HostKit.HostKitType.Name}BuilderExtensions", context.HostKit.Accessibility)
{
IsStatic = true,
Expand Down Expand Up @@ -96,7 +96,7 @@ static void BuildExtensionMethod(CodeWriter writer, OutputContext context)
}

using (
writer.WriteMethodScope(
writer.MethodScope(
new(
context.HostKit.ExtensionMethodName,
TypeLibrary.IDistributedApplicationBuilder,
Expand Down Expand Up @@ -134,11 +134,9 @@ static void BuildExtensionMethod(CodeWriter writer, OutputContext context)
terminate: false
)
.NewLine()
.Indented(w =>
w.WriteInvocation($".Get<{context.HostKit.OptionsType}>", [], terminate: false)
.WriteInvocation($".Get<{context.HostKit.OptionsType}>", [], terminate: false)
.Write(" ?? new();")
.NewLine()
);
.NewLine();
}

writer.Comment("Create an instance of the generated host kit and configure it.");
Expand All @@ -150,17 +148,15 @@ static void BuildExtensionMethod(CodeWriter writer, OutputContext context)
: ["onBuilt", "onConfigured"],
terminate: false
);
writer.WriteLine(";");
writer.Line(";");

writer
.NewLine()
.WriteInvocationLine("hostKit.Build", ["builder"])
.WriteInvocationLine("hostKit.Configure", [])
.NewLine()
.WriteInvocationLine("builder.Services.AddSingleton", ["hostKit"])
.NewLine();
.MethodCallOn("hostKit", "Build", ["builder"])
.MethodCallOn("hostKit", "Configure")
.MethodCallOn("builder.Services", "AddSingleton", ["hostKit"]);

writer.WriteLine("return builder;");
writer.Return("builder");
}
}
}
49 changes: 23 additions & 26 deletions src/src/SourceGeneration/Helpers/CodeGenEmiiter.HostKit.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Immutable;
using Purview.Aspire.ResourceKit.SourceGeneration.Models;
using System.Collections.Immutable;

namespace Purview.Aspire.ResourceKit.SourceGeneration.Helpers;

Expand All @@ -11,7 +11,7 @@ static void EmitHostKit(OutputContext context, CancellationToken cancellationTok

context.Info($"Generating {context.HostKit.HostKitType.MetadataFullName}...");

using var nsScope = context.Writer.WriteBlockNamespaceScope(context.HostKit.HostKitType.Namespace);
using var nsScope = context.Writer.BlockNamespaceScope(context.HostKit.HostKitType.Namespace);

var primaryConstructorParameters = ImmutableArray.CreateBuilder<ParameterDeclarationOptions>();
primaryConstructorParameters.Add(
Expand All @@ -35,7 +35,7 @@ static void EmitHostKit(OutputContext context, CancellationToken cancellationTok
using (
context
.Writer.XmlSummary("Represents the generated Host Kit and composes all discovered Resources Kits")
.WriteClassScope(
.ClassScope(
new(context.HostKit.HostKitType)
{
IsPartial = true,
Expand All @@ -51,7 +51,7 @@ static void EmitHostKit(OutputContext context, CancellationToken cancellationTok
{
context
.Writer.XmlSummary($"Gets the Host Kit options <see cref=\"{context.HostKit.OptionsType}\"/>.")
.WriteProperty(
.Property(
new("Options", context.HostKit.OptionsType, TypeDeclarationAccessibility.Public)
{
HasGetter = true,
Expand Down Expand Up @@ -95,12 +95,12 @@ static void EmitResourceKitBase(OutputContext context, CancellationToken cancell
$"Generating Resource Kit base class for host kit: {context.Model.HostKit.Value.HostKitType.Name}"
);

using (context.Writer.WriteBlockNamespaceScope(context.Model.HostKit.Value.ResourceKitBaseType.Namespace))
using (context.Writer.BlockNamespaceScope(context.Model.HostKit.Value.ResourceKitBaseType.Namespace))
{
context
.Writer.XmlSummary("Represents a typed base class for all generated Resource Kits for the Host Kit.")
.WriteClass(
new(context.Model.HostKit.Value.ResourceKitBaseType.Name, context.Model.HostKit.Value.Accessibility)
.Class(
new(context.Model.HostKit.Value.ResourceKitBaseType, context.Model.HostKit.Value.Accessibility)
{
IsPartial = true,
IsAbstract = true,
Expand All @@ -115,7 +115,7 @@ static void EmitResourceKitBase(OutputContext context, CancellationToken cancell
},
body =>
body.XmlSummary("Initializes a new instance of the Host Kit Resource Kit base class.")
.WriteConstructor(
.Constructor(
new(
context.Model.HostKit.Value.ResourceKitBaseType,
TypeDeclarationAccessibility.Protected
Expand Down Expand Up @@ -161,30 +161,27 @@ var resourceKit in context
)
.XmlException(TypeLibrary.ArgumentNullException, "Thrown if the resource is set to null.");

context.Writer.WriteProperty(
context.Writer.Property(
new(resourceKit.PropertyName, resourceKit.ResourceKitType, TypeDeclarationAccessibility.Public)
{
HasGetter = true,
HasSetter = true,
SetterAccessibility = TypeDeclarationAccessibility.Private,
},
writeGetterBody =>
writeGetterBody.WriteLine(
writeGetterBody.Line(
$"return field ?? throw new {TypeLibrary.InvalidOperationException}(\"The '{resourceKit.PropertyName}' resource has not been initialized. Call Build first.\");"
),
writeSetterBody =>
{
writeSetterBody
.WriteLine(TypeLibrary.ArgumentNullException.StaticMember("ThrowIfNull(value);"))
.NewLine();

using (writeSetterBody.OpenBlockScope("if (field is not null)"))
writeSetterBody.WriteThrow(
writeSetterBody.MethodCallOn(TypeLibrary.ArgumentNullException, "ThrowIfNull(value)");
using (writeSetterBody.IfBlockScope("if (field is not null)"))
writeSetterBody.Throw(
TypeLibrary.InvalidOperationException,
$"The '{resourceKit.PropertyName}' resource has already been initialized."
);

writeSetterBody.NewLine().WriteAssignment("field", "value");
writeSetterBody.Assignment("field", "value");
}
);
}
Expand All @@ -198,7 +195,7 @@ static void GenerateBuildMethod(OutputContext context, CancellationToken cancell

context.Writer.XmlInheritDoc();
using (
context.Writer.WriteMethodScope(
context.Writer.MethodScope(
new("Build", TypeDeclarationAccessibility.Public)
{
IsOverride = true,
Expand All @@ -207,7 +204,7 @@ static void GenerateBuildMethod(OutputContext context, CancellationToken cancell
)
)
{
context.Writer.WriteLine(TypeLibrary.ArgumentNullException.StaticMember("ThrowIfNull(builder);")).NewLine();
context.Writer.MethodCallOn(TypeLibrary.ArgumentNullException, "ThrowIfNull(builder);");

foreach (
var resourceKit in context.ResourceKits.AsImmutableArray().SelectMany(r => r.Items.AsImmutableArray())
Expand Down Expand Up @@ -246,22 +243,22 @@ var resourceKit in context
)
{
cancellationToken.ThrowIfCancellationRequested();
context.Writer.WriteInvocationLine("AddResource", [$"{resourceKit.PropertyName}"]);
context.Writer.MethodCall("AddResource", [resourceKit.PropertyName]);
}
}

context
.Writer.NewLine()
.Comment("Now the additional post-build func builder")
.WriteInvocationLine("onBuilt?.Invoke", ["this", "builder"]);
.MethodCallOn("onBuilt?", "Invoke", ["this", "builder"]);

context
.Writer.NewLine()
.Comment(
"Now that we've populated all of the resources, call the base classes",
"Build method to register the app resources with the builder."
)
.WriteInvocationLine("base.Build", ["builder"]);
.MethodCallOn("base", "Build", ["builder"]);
}
}

Expand All @@ -273,7 +270,7 @@ static void GenerateConfigureMethod(OutputContext context, CancellationToken can

context.Writer.XmlInheritDoc();
using (
context.Writer.WriteMethodScope(new("Configure", TypeDeclarationAccessibility.Public) { IsOverride = true })
context.Writer.MethodScope(new("Configure", TypeDeclarationAccessibility.Public) { IsOverride = true })
)
{
context
Expand All @@ -297,7 +294,7 @@ static void GenerateHostKitOptionsClass(OutputContext context, CancellationToken
context.Writer.NewLine().XmlSummary($"Typed settings for ${CodeWriter.XmlSee(context.HostKit.OptionsType)}.");

using (
context.Writer.WriteClassScope(
context.Writer.ClassScope(
new(context.HostKit.OptionsType.Name, TypeDeclarationAccessibility.Public)
{
IsSealed = true,
Expand All @@ -308,7 +305,7 @@ static void GenerateHostKitOptionsClass(OutputContext context, CancellationToken
{
context
.Writer.XmlSummary("Configuration section name for host kit options.")
.WriteField(
.Field(
new("SectionName", PurviewTypeLibrary.System.String, TypeDeclarationAccessibility.Public)
{
IsConst = true,
Expand All @@ -332,7 +329,7 @@ var resourceKit in context
$"Gets or sets options for {CodeWriter.XmlSee(resourceKit.ResourceKitType)}.",
$"{CodeWriter.XmlSee(resourceKit.OptionsType)} for specific configuration options."
)
.WriteProperty(
.Property(
new(resourceKit.PropertyName, resourceKit.OptionsType, TypeDeclarationAccessibility.Public)
{
HasGetter = true,
Expand Down
Loading
Loading