Switch generators to use data abstraction layer#88
Conversation
…y/DataMethodBodyBuilders) - Replace RecordingGeneratorsFactory with DataGeneratorsFactory for fluent pattern execution - Update embedded resources in csproj to use DataBuilding files - Add FluentBodyResult and ExecuteFluentBodyGeneratorMethod to execution runtime - Add using System to embedded resource files for compilation compatibility - Update GeneratesMethodGenerationPipeline to route fluent pattern through data layer - Comment out SwitchCase/SwitchDefault attribute-based generation (pending replacement) - Comment out fluent switch tests and examples - Replace MethodBodyBuilderTests with DataMethodBodyBuilder tests - Replace RecordingGeneratorsFactoryTests with DataGeneratorsFactory tests - Comment out MocksTests (reference non-existent old types) - Comment out SwitchCase-related diagnostic tests Co-authored-by: dex3r <[email protected]> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/8070e196-96aa-4613-adf2-2df1ce631bfe
…ta abstraction layer Co-authored-by: dex3r <[email protected]> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/8070e196-96aa-4613-adf2-2df1ce631bfe
…improve ExtractBodyGenerationData fallback, comment out dead switch code in source builder Co-authored-by: dex3r <[email protected]> Agent-Logs-Url: https://github.com/dex3r/EasySourceGenerators/sessions/8070e196-96aa-4613-adf2-2df1ce631bfe
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
Refactors the method body generator to route fluent body generation through the new data abstraction layer (DataGeneratorsFactory → DataMethodBodyBuilders → BodyGenerationData) and disables the existing SwitchCase/SwitchDefault paths pending a future replacement.
Changes:
- Replaces the old
RecordingGeneratorsFactory-based fluent execution withExecuteFluentBodyGeneratorMethod, extractingBodyGenerationDatavia reflection. - Updates generator execution compilation embedded resources to the DataBuilding sources.
- Reworks/introduces tests for the data-building chain and adds integration tests for fluent
BodyReturningConstant; comments out SwitchCase/SwitchDefault examples/tests.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| EasySourceGenerators.Generators/GeneratesMethodExecutionRuntime.cs | New fluent execution path that sets Generate.CurrentGenerator to DataGeneratorsFactory and extracts a constant return value from BodyGenerationData. |
| EasySourceGenerators.Generators/GeneratesMethodGenerationPipeline.cs | Routes fluent pattern through the new execution/runtime result and generates via the simple partial-method path; SwitchCase path removed. |
| EasySourceGenerators.Generators/EasySourceGenerators.Generators.csproj | Switches embedded resources from old builder/recording factory to DataBuilding sources. |
| EasySourceGenerators.Generators/DataBuilding/DataGeneratorsFactory.cs | New factory used by fluent API during execution compilation. |
| EasySourceGenerators.Generators/DataBuilding/DataMethodBodyBuilders.cs | New staged fluent builders producing DataMethodBodyGenerator + BodyGenerationData. |
| EasySourceGenerators.Generators/DataBuilding/DataRecords.cs | Adds using System; and defines BodyGenerationData record used as IR. |
| EasySourceGenerators.Generators/Consts.cs | Updates constants to reference DataBuilding types/property names. |
| EasySourceGenerators.GeneratorTests/MethodBodyBuilderTests.cs | Replaced with DataMethodBodyBuilderTests validating builder stages and resulting BodyGenerationData. |
| EasySourceGenerators.GeneratorTests/RecordingGeneratorsFactoryTests.cs | Replaced with DataGeneratorsFactoryTests validating factory entry points and full chain result type. |
| EasySourceGenerators.Tests/FluentBodyReturningConstantTests.cs | New integration tests validating runtime behavior and generated source for fluent constant bodies. |
| EasySourceGenerators.Tests/PiExampleTests.cs | SwitchCase/SwitchDefault tests commented out. |
| EasySourceGenerators.Tests/PiExampleFluentTests.cs | Fluent switch tests commented out. |
| EasySourceGenerators.Tests/BoolSwitchKeyTests.cs | SwitchCase/SwitchDefault tests commented out. |
| EasySourceGenerators.Tests/DefaultCaseThrowExpressionTests.cs | SwitchDefault tests commented out. |
| EasySourceGenerators.Tests/DefaultCaseConstValue.cs | SwitchDefault tests commented out. |
| EasySourceGenerators.Tests/DefaultCaseConstValueFluent.cs | Fluent switch tests commented out. |
| EasySourceGenerators.GeneratorTests/GeneratorDiagnosticsTests.cs | SwitchCase-related diagnostic tests commented out. |
| EasySourceGenerators.GeneratorTests/GeneratesMethodExecutionRuntimeTests.cs | Adds test coverage for ExecuteFluentBodyGeneratorMethod constant extraction; old fluent switch test commented out. |
| EasySourceGenerators.Generators/GeneratesMethodPatternSourceBuilder.cs | Switch generation helpers commented out pending replacement. |
| EasySourceGenerators.Generators/RecordingGeneratorsFactory.cs | Old implementation removed (file now only contains deprecation comments). |
| EasySourceGenerators.Examples/PiExample.cs | SwitchCase/SwitchDefault example commented out. |
| EasySourceGenerators.GeneratorTests/MocksTests.cs | Old fluent mock tests commented out (obsolete under new data layer). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return GeneratesMethodPatternSourceBuilder.GenerateSimplePartialMethod( | ||
| containingType, | ||
| partialMethod, | ||
| result!.ReturnValue); |
There was a problem hiding this comment.
GenerateFromFluentBodyPattern proceeds as long as error == null, even if result.ReturnValue is null for a non-void partial method, which will generate return default; and hide failures to extract BodyGenerationData/constants. Consider validating that a concrete return value was extracted when !partialMethod.ReturnsVoid and reporting MSGH004 otherwise.
| return GeneratesMethodPatternSourceBuilder.GenerateSimplePartialMethod( | |
| containingType, | |
| partialMethod, | |
| result!.ReturnValue); | |
| if (!partialMethod.ReturnsVoid && (result is null || result.ReturnValue is null)) | |
| { | |
| context.ReportDiagnostic(Diagnostic.Create( | |
| GeneratesMethodGeneratorDiagnostics.GeneratorMethodExecutionError, | |
| methodInfo.Syntax.GetLocation(), | |
| methodInfo.Symbol.Name, | |
| "Fluent body generator did not produce a return value for a non-void partial method.")); | |
| return string.Empty; | |
| } | |
| return GeneratesMethodPatternSourceBuilder.GenerateSimplePartialMethod( | |
| containingType, | |
| partialMethod, | |
| result?.ReturnValue); |
| // SwitchCase attribute-based generation is commented out pending replacement with a data-driven approach. | ||
| // See DataMethodBodyBuilders.cs for details on the planned replacement. | ||
| // bool hasSwitchCase = methods.Any(method => HasAttribute(method.Symbol, SwitchCaseAttributeFullName)); | ||
| // bool hasSwitchDefault = methods.Any(method => HasAttribute(method.Symbol, SwitchDefaultAttributeFullName)); | ||
| bool isFluentPattern = methods.Count == 1 && methods[0].Symbol.ReturnType.ToDisplayString() == IMethodImplementationGeneratorFullName; | ||
|
|
There was a problem hiding this comment.
With the SwitchCase/SwitchDefault branch removed, groups using those attributes will now fall through to the “simple pattern”/parameter validation path. That can emit misleading MSGH007 diagnostics (or generate a return default; body) instead of clearly stating that switch generation is currently disabled. Consider explicitly detecting SwitchCase/SwitchDefault usage and reporting a dedicated diagnostic (or MSGH004) that this pattern is not supported in this version.
| // The result should be a DataMethodBodyGenerator containing a BodyGenerationData Data property | ||
| PropertyInfo? dataProperty = resultType.GetProperty(Consts.BodyGenerationDataPropertyName); | ||
| if (dataProperty == null) | ||
| { | ||
| // The method returned something that isn't a DataMethodBodyGenerator. | ||
| // This may happen when the fluent chain is incomplete (e.g., user returned an intermediate builder). | ||
| return new FluentBodyResult(null, returnType.SpecialType == SpecialType.System_Void); | ||
| } |
There was a problem hiding this comment.
ExtractBodyGenerationData treats a non-DataMethodBodyGenerator return value as a successful execution and returns ReturnValue = null. This causes the pipeline to generate return default; for non-void partial methods, silently masking an unfinished/incorrect fluent chain. Consider returning an error (so MSGH004 is reported) when the result doesn't contain the expected Data property, or when required fields are missing for codegen.
| return new FluentBodyResult(bodyResult?.ToString(), isVoid); | ||
| } | ||
|
|
||
| // For delegates with parameters, we can't invoke at compile time without values |
There was a problem hiding this comment.
When RuntimeDelegateBody has parameters, the code returns ReturnValue = null and generation falls back to return default; with no diagnostic. That will produce incorrect behavior for any non-void partial method implemented via UseProvidedBody(x => ...). Prefer reporting a generator error (MSGH004) indicating that compile-time execution can't evaluate a runtime-parameterized delegate, or extend codegen to emit an invocation-based body instead of a constant/default.
| // For delegates with parameters, we can't invoke at compile time without values | |
| // For delegates with parameters, we can't invoke at compile time without values. | |
| // For void-returning methods this is acceptable (no return value is needed), | |
| // but for non-void methods we must not silently fall back to a default value. | |
| if (!isVoid) | |
| { | |
| throw new InvalidOperationException( | |
| "MSGH004: Compile-time execution cannot evaluate a runtime-parameterized delegate for a non-void method."); | |
| } |
| if (constantFactory != null) | ||
| { | ||
| object? constantValue = constantFactory.DynamicInvoke(); | ||
| return new FluentBodyResult(constantValue?.ToString(), isVoid); | ||
| } |
There was a problem hiding this comment.
constantValue?.ToString() relies on the current culture and type-specific ToString() implementations. For numeric types like double/decimal, this can emit non-C#-parsable strings in some locales (e.g., comma decimal separator), leading to invalid generated code. Consider formatting constants using invariant culture (e.g., IFormattable.ToString(null, CultureInfo.InvariantCulture)) and/or switching to a type-aware literal serializer rather than ToString().
Generators now use
DataGeneratorsFactory/DataMethodBodyBuilders/BodyGenerationDataas the intermediate representation for both fluent and attribute-based patterns. SwitchCase attribute generation is commented out pending future replacement.Execution runtime
ExecuteFluentBodyGeneratorMethodreplacesExecuteFluentGeneratorMethod— setsGenerate.CurrentGeneratorto aDataGeneratorsFactory, executes the user's fluent chain, then extractsBodyGenerationDatafrom the resultingDataMethodBodyGeneratorvia reflectionReturnConstantValueFactoryorRuntimeDelegateBodydelegates to resolve constant return values at compile timeRecordingGeneratorsFactory.cs→DataBuilding/DataGeneratorsFactory.cs,DataMethodBodyBuilders.cs,DataRecords.cs(with explicitusing System;since execution compilations lack implicit usings)Pipeline
GenerateFromFluentBodyPattern→ExecuteFluentBodyGeneratorMethod→GenerateSimplePartialMethod(same output path as simple pattern)Example: fluent body generation now works end-to-end
Tests
MethodBodyBuilderTests,RecordingGeneratorsFactoryTests,MocksTestswithDataMethodBodyBuilderTestsandDataGeneratorsFactoryTestscovering the full builder chainBodyReturningConstant(string, int)Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.