Skip to content

Commit 4cf02dd

Browse files
Copilotdex3r
andauthored
Fix generator runtime assembly resolution for Abstractions and restore fluent source emission (#16)
* Initial plan * Fix generator assembly loading and fluent fallback generation Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com> * Update MattSourceGenHelpers.Generators/GeneratesMethodExecutionRuntime.cs --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: dex3r <3155725+dex3r@users.noreply.github.com> Co-authored-by: Mateusz Krzaczek <dex3r@users.noreply.github.com>
1 parent 4ceaf02 commit 4cf02dd

3 files changed

Lines changed: 31 additions & 18 deletions

File tree

MattSourceGenHelpers.Generators/GeneratesMethodExecutionRuntime.cs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.Reflection;
77
using System.Runtime.Loader;
88
using System.Text;
9-
using MattSourceGenHelpers.Abstractions;
109

1110
namespace MattSourceGenHelpers.Generators;
1211

@@ -16,6 +15,13 @@ internal sealed record SwitchBodyData(
1615

1716
internal static class GeneratesMethodExecutionRuntime
1817
{
18+
// The Abstraction assembly cannot be referenced directly here, even though the IDE makes it look like it could. However, the source generation process will fail if it is.
19+
private const string AbstractionsAssemblyName = "MattSourceGenHelpers.Abstractions";
20+
private const string GenerateTypeName = "MattSourceGenHelpers.Abstractions.Generate";
21+
private const string RecordingGeneratorsFactoryTypeName = "MattSourceGenHelpers.Abstractions.RecordingGeneratorsFactory";
22+
private const string CurrentGeneratorPropertyName = "CurrentGenerator";
23+
private const string LastRecordPropertyName = "LastRecord";
24+
1925
internal static (string? value, string? error) ExecuteSimpleGeneratorMethod(
2026
IMethodSymbol generatorMethod,
2127
IMethodSymbol partialMethod,
@@ -56,37 +62,37 @@ internal static (SwitchBodyData? record, string? error) ExecuteFluentGeneratorMe
5662
Path.GetFileNameWithoutExtension(reference.FilePath),
5763
assemblyName.Name,
5864
StringComparison.OrdinalIgnoreCase));
59-
return match?.FilePath != null ? context.LoadFromAssemblyPath(match.FilePath) : null;
65+
return match?.FilePath != null
66+
? context.LoadFromAssemblyPath(ResolveImplementationAssemblyPath(match.FilePath))
67+
: null;
6068
};
6169

6270
Assembly assembly = loadContext.LoadFromStream(stream);
6371

64-
string abstractionAssemblyName = typeof(Generate).Assembly.GetName().Name!;
65-
6672
PortableExecutableReference? abstractionsReference = compilation.References
6773
.OfType<PortableExecutableReference>()
6874
.FirstOrDefault(reference => reference.FilePath is not null && string.Equals(
6975
Path.GetFileNameWithoutExtension(reference.FilePath),
70-
abstractionAssemblyName,
76+
AbstractionsAssemblyName,
7177
StringComparison.OrdinalIgnoreCase));
7278

7379
if (abstractionsReference?.FilePath == null)
7480
{
75-
return (null, $"Could not find {abstractionAssemblyName} reference in compilation");
81+
return (null, $"Could not find {AbstractionsAssemblyName} reference in compilation");
7682
}
7783

7884
string abstractionsAssemblyPath = ResolveImplementationAssemblyPath(abstractionsReference.FilePath);
7985
Assembly abstractionsAssembly = loadContext.LoadFromAssemblyPath(abstractionsAssemblyPath);
8086

81-
Type? generatorStaticType = abstractionsAssembly.GetType(typeof(Generate).FullName!);
82-
Type? recordingFactoryType = abstractionsAssembly.GetType(typeof(RecordingGeneratorsFactory).FullName!);
87+
Type? generatorStaticType = abstractionsAssembly.GetType(GenerateTypeName);
88+
Type? recordingFactoryType = abstractionsAssembly.GetType(RecordingGeneratorsFactoryTypeName);
8389
if (generatorStaticType == null || recordingFactoryType == null)
8490
{
85-
return (null, $"Could not find {typeof(Generate).FullName} or {typeof(RecordingGeneratorsFactory).FullName} types in Abstractions assembly");
91+
return (null, $"Could not find {GenerateTypeName} or {RecordingGeneratorsFactoryTypeName} types in Abstractions assembly");
8692
}
8793

8894
object? recordingFactory = Activator.CreateInstance(recordingFactoryType);
89-
PropertyInfo? currentGeneratorProperty = generatorStaticType.GetProperty(nameof(Generate.CurrentGenerator), BindingFlags.Public | BindingFlags.Static);
95+
PropertyInfo? currentGeneratorProperty = generatorStaticType.GetProperty(CurrentGeneratorPropertyName, BindingFlags.Public | BindingFlags.Static);
9096
currentGeneratorProperty?.SetValue(null, recordingFactory);
9197

9298
string typeName = generatorMethod.ContainingType.ToDisplayString();
@@ -104,7 +110,7 @@ internal static (SwitchBodyData? record, string? error) ExecuteFluentGeneratorMe
104110

105111
generatorMethodInfo.Invoke(null, null);
106112

107-
PropertyInfo? lastRecordProperty = recordingFactoryType.GetProperty(nameof(RecordingGeneratorsFactory.LastRecord));
113+
PropertyInfo? lastRecordProperty = recordingFactoryType.GetProperty(LastRecordPropertyName);
108114
object? lastRecord = lastRecordProperty?.GetValue(recordingFactory);
109115
if (lastRecord == null)
110116
{
@@ -154,7 +160,9 @@ internal static (string? value, string? error) ExecuteGeneratorMethodWithArgs(
154160
Path.GetFileNameWithoutExtension(reference.FilePath),
155161
assemblyName.Name,
156162
StringComparison.OrdinalIgnoreCase));
157-
return match?.FilePath != null ? context.LoadFromAssemblyPath(match.FilePath) : null;
163+
return match?.FilePath != null
164+
? context.LoadFromAssemblyPath(ResolveImplementationAssemblyPath(match.FilePath))
165+
: null;
158166
};
159167

160168
Assembly assembly = loadContext.LoadFromStream(stream);

MattSourceGenHelpers.Generators/GeneratesMethodPatternSourceBuilder.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ internal static string GenerateSimplePartialMethod(
142142
}
143143

144144
string methodName = memberAccessExpression.Name.Identifier.Text;
145-
if (methodName is not ("RuntimeBody" or "CompileTimeBody"))
145+
if (methodName is not ("RuntimeBody" or "CompileTimeBody" or "WithBody"))
146146
{
147147
continue;
148148
}
@@ -181,7 +181,16 @@ private static string GenerateSwitchMethodSource(
181181
StringBuilder builder = new();
182182
AppendNamespaceAndTypeHeader(builder, containingType, partialMethod);
183183

184-
string switchParameterName = partialMethod.Parameters.Length > 0 ? partialMethod.Parameters[0].Name : "arg";
184+
if (partialMethod.Parameters.Length == 0)
185+
{
186+
string fallbackExpression = defaultExpression ?? "default";
187+
builder.AppendLine($" return {fallbackExpression};");
188+
builder.AppendLine(" }");
189+
builder.AppendLine("}");
190+
return builder.ToString();
191+
}
192+
193+
string switchParameterName = partialMethod.Parameters[0].Name;
185194
builder.AppendLine($" switch ({switchParameterName})");
186195
builder.AppendLine(" {");
187196

MattSourceGenHelpers.Generators/MattSourceGenHelpers.Generators.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
1010
</PropertyGroup>
1111

12-
<ItemGroup>
13-
<ProjectReference Include="..\MattSourceGenHelpers.Abstractions\MattSourceGenHelpers.Abstractions.csproj" />
14-
</ItemGroup>
15-
1612
<ItemGroup>
1713
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
1814
</ItemGroup>

0 commit comments

Comments
 (0)