[9.x.x] Convert RuleGenerator, ReportGenerator and FunctionGenerator to Java and migrate them to the fluent API - #1375
Merged
Conversation
Move RuleGenerator from the deprecated XtendJavaClassGenerator base class to FluentRObjectJavaClassGenerator, so generateClass returns a CodeRenderer. The class body is still produced as an Xtend template by the (not-yet-migrated) FunctionGenerator, so add a reusable compatibility bridge, LegacyTemplateRenderer, that adapts a legacy StringConcatenationClient class body into a CodeRenderer. Layout is produced by Xtend's StringConcatenation (as the legacy ImportManagerExtension#buildClass does), while embedded JavaClasses and Methods are resolved against the RecordingCodeWriter so the fluent file builder collects their imports and resolves their identifiers. Output is byte-identical, letting generators move onto the fluent API one at a time, before their templates have been rewritten with the fluent CodeWriter API.
Like RuleGenerator, move ReportGenerator from the deprecated RObjectJavaClassGenerator base class to FluentRObjectJavaClassGenerator, with generateClass returning a CodeRenderer. The class body is still produced as an Xtend template by FunctionGenerator, so wrap it with LegacyTemplateRenderer. The @RosettaReport and @RuneLabelProvider annotation bodies, previously Xtend '''...''' templates, are built as StringConcatenationClient instances (the same idiom already used in AliasUtil); the label-provider class is embedded as an object so its import is registered.
Ported from finos#1293, with the choice-type implied-key handling (finos#1252) omitted: that logic depends on RosettaDeepFeatureCall.feature being widened from Attribute to RosettaFeature, an EMF API change that hasn't been backported to 9.x.x. FunctionOperationGeneratorTest.java, which only tests that logic, is dropped for the same reason.
Make classBody return a CodeRenderer (like dispatchClassBody and the original StringConcatenationClient-returning classBody) instead of being a void method taking a CodeWriter, so rBuildClass returns it directly. Render the default class declaration inline (class XDefault extends ...) instead of via RGeneratedJavaClass#asClassDeclaration, which lets defaultClass be typed as JavaClass<?> and removes one legacy-template-fragment bridge usage.
Change RGeneratedJavaClass#asClassDeclaration to return a dual TargetLanguage representation that renders via the fluent CodeWriter API and, through a reverse bridge, still appends to the legacy Xtend template machinery. FunctionGenerator now renders the default class via asClassDeclaration() again (so defaultClass is an RGeneratedJavaClass<?>), and the not-yet-migrated generators that embed it in Xtend templates keep working unchanged. Extract the reverse bridge TargetStringConcatenationCodeWriter from JavaExpression into a reusable public class (the counterpart of CodeWriterTargetStringConcatenation). For consistency with FunctionGenerator#classBody, DeepPathUtilGenerator#renderClass now returns a CodeRenderer instead of being a void method taking a CodeWriter.
…sion FluentJavaClassGenerator#buildClass had been made public so FunctionGeneratorHelper could call it directly to assemble a single function's class file from its CodeRenderer. That widened an internal detail of the generator base class purely to serve one external caller, instead of exposing an independently-usable service the way ImportManagerExtension always was for the legacy Xtend path. Extract buildClass into FluentImportManager, injected the same way XtendJavaClassGenerator injects ImportManagerExtension, and have FunctionGeneratorHelper depend on it directly instead of reaching through the generator instance. buildClass reverts to protected.
…tionGenerator output format FunctionGenerator's fluent-API migration (previous commit) changed the generator's whitespace conventions (4-space indent, no blank line after an opening brace, condensed Javadoc). This still-Xtend test file (never migrated on 9.x.x, unlike its main-branch counterpart FunctionOperationGeneratorTest) asserts against hardcoded expected Java source, so it needed its expectations regenerated to match. No generator or production logic changed; only the literal expected strings were regenerated from a passing test run's actual output.
JayasriR
approved these changes
Aug 27, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
9.x.x backport of #1293.
FunctionGenerator's operation-to-meta logic is backported without the choice-type implied-key handling from #1252: that logic needs
RosettaDeepFeatureCall.featurewidened fromAttributetoRosettaFeature, an EMF model/API change that hasn't been backported to 9.x.x (it would change the generatedgetFeature()return type for anything compiled against 9.x.x's EMF classes).FunctionOperationGeneratorTest.java, which only exercises that logic, is dropped for the same reason — it isn't present on 9.x.x today either.Everything else — the Xtend→Java conversion and the fluent
CodeRendererAPI migration forRuleGenerator,ReportGenerator,FunctionGenerator, and theDeepPathUtilGeneratoralignment — carries over as-is.The last commit updates
CalculationFunctionGeneratorTest(9.x.x's still-Xtend equivalent of main'sFunctionOperationGeneratorTest, never migrated here, so I missed it while scoping the initial coverage check): FunctionGenerator's new output has different whitespace conventions than the old Xtend-template generator, so this hardcoded-expected-string test needed its expectations regenerated. No generator behaviour changed — fullmvn clean installnow passes with 0 failures across all modules.Test coverage per production file changed
reports/RuleGenerator.java(+ deleted.xtend) —RosettaRuleGeneratorTest(24/24 pass)reports/ReportGenerator.java(+ deleted.xtend) —ReportGeneratorTest(5/5 pass)function/FunctionGenerator.java(+ deleted.xtend) —FunctionGeneratorTest(148/148),FunctionGeneratorMetaTest(47/47),CalculationFunctionGeneratorTest(9/9),ListOperationTest(71/71),RosettaBinaryOperationTest(11/11)expression/DeepPathUtilGenerator.java—DeepPathRegressionTest(88/88); also exercised transitively byFunctionGeneratorMetaTestFluentJavaClassGenerator.java,statement/builder/JavaExpression.java,types/RGeneratedJavaClass.java,util/CodeWriterTargetStringConcatenation.java,util/TargetStringConcatenationCodeWriter.java— shared base class / rendering plumbing used by all of the above generators; exercised transitively by every test listedutil/FluentImportManager.java(new) — exercised viaFunctionGeneratorHelper(test helper used byFunctionGeneratorTest,FunctionGeneratorMetaTest,ListOperationTest,RosettaBinaryOperationTest)Also ran
JavaNameEscapingTest(115/115) since the name-escaping regression fixtures underfunctions/shifted.Test plan
mvn clean install -o— full multi-module build, all tests, 0 failures