Skip to content

[Generator] Refactor the Metamodel generator to not use Ring anymore and simplify it - #1122

Merged
jecisc merged 137 commits into
moosetechnology:developmentfrom
jecisc:remove-ring
May 28, 2026
Merged

[Generator] Refactor the Metamodel generator to not use Ring anymore and simplify it#1122
jecisc merged 137 commits into
moosetechnology:developmentfrom
jecisc:remove-ring

Conversation

@jecisc

@jecisc jecisc commented Apr 28, 2026

Copy link
Copy Markdown
Member

Ring removal

This is a big change. This PR removes the usage of Ring in the Metamodel builder.

Before the process was:
Execute the generator to create an intermediate model -> Generate ring entities -> Filter ring entities to remove what would have no impact -> create changes -> generate the real code -> build a Fame model to use as descriptions

Now the process is:
Execute the generator to create an intermediate model -> Generate changes -> Filter the changes -> generate the code -> build the Fame model to use as descriptions

This is still complex but it's a big step to simplify things.

Using Ring had a lot of cons such as:

  • It's easily broken in Pharo and since there is not much tests in the code generation, it's not detected before Moose breaks
  • It does not support all features we need (like management of extensions for classes that are not in the ring model) and this made some features bypass all layers and having hacks
  • It's easy to mix layers in the code
  • People tested features by testing the Ring model but this does not mean that the generated code is right
  • We currently have 4 models for our code (FmxMB one, ring, changes and Fame) which is overkill...

This change fixes multiple bugs:

  • The generation of MooseModel was bugged and worked only by chance. But any new feature to add to it could have broken everything
  • The generation of navigations was done 3 times. But now it's removed (I cherry picked this change in another PR so it's already in Moose)
  • The generation of extension methods was breaking all layers but now it's going through the normal way which will prevent some bugs
  • A clean generation was not taking traits methods removal or trait precedence into account and generated wrong code
  • Generation of properties on remote entities could not happen in some cases
  • Fix the generation bug happening of Moose 13 - Pharo 14 CI
  • Fix bug removing extension methods from other generators during generation
  • Generate #package: pragma en remote setters
  • Fix bug in some classes removals (Originally we generated only annotated classes so we used the annotation to know if a class was from the generator. Now we need to includes also groups and the importing context)
  • Model classes were the only classes using the full name for the fame annotation instead of the name. Now they are coherent with the other annotations.
  • Fix test checking that generators are up to date to take remote changes into account (it was ignoring all remote changes previously)
  • Fix a bug of the generator removing classes that are not metadescribed if it uses a trait that is metadescribed
  • Fix a bug in #allTransitiveTraits that made it includes superclasses in the result

Fixes #983
Fixes #1135

Refactoring of the visitor generator

I did multiple changes in the visitor generator to make it more usable.

  • Now we do not visit relations to a parent because it caused infinite loops. Most analysis are top down, not bottom up
  • Now the #accept: methods are implemented only once in MooseObject to avoid conflicts between languages when visiting remote entities
  • Now it is not necessary anymore to have a visitor in all submetamodels. The visitors are standalone
  • Now if a class has a trait in its superclasses and in its trait composition (recursively), we visit it only once while visiting the superclass

Simplifications

Simplify relations

I also shipped some simplifications with this PR. The main one is the merging of FmxMBRelation and FmxMBRelationSide.

FmxMBRelation was saving 2 relations sides. FmxMBBehavior was saving both the relation in #relations and the sides in #properties.

I renamed all the API related to properties and relations of FmxMBBehavior to ensure we know if we have properties, relations or both.

Now we only save the relations sides. I removed the FmxMBRelation. Instead a relation side knows its opposite directly.

In FmxMBRelation we had a concept of direction. A relation was from a side to another. But this is wrong, a relation is bidirectional. What defines the direction of a relation should not be the relation itself, but the behavioral holding the relation.

Fixes #1124

Simplify Relation accessors generation

Until now, we saved a relation generation strategy in FmxMBRelationSide. This strategy was set manually when creating a relation side.

The name of the strategy did not help to understand them and they had no comment.

I did multiple improvements:

  • Simplify the class comment generation to not rely on those strategy since we have all the info in the relations directly
  • Generation strategy had the relation duplicated. Once as an ivar and once as a parameter of the methods generating the code. I removed the ivar and added a default instance so that generation is less costly.
  • Generation strategy is now resolved at the generation and not at the construction of the model. This has multiple impacts. First, it removes a source of bug since the users of relation does not have to select is manually. Second, I want to remove the generation from FmxMB model and this cuts a dependency to classes used only for generation
  • I merged the RemoteStrategy and NonRemoteStrategy strategies into AttributeStrategy
  • Renamed StandardStrategy to SlotStrategy
  • Added comments

Rework visitors and introduce a visitor to generate the MM code

I did improvements of the visitors and with those changes I updated the way to generate the code.

Instead of having all the code generation in the FmxMB model classes I moved it to a visitor. I have one for the normal changes and one for the remote subbuilders.

I also introduced a FmxMBMethodFactory to simplify the generation code. The generation code can be quite verbose. The introduction of this class group the methods to generate and simplify the generation code.

Other

  • I remove the concept of #classGeneralization (superclasses) from FmxMBBehavior to have it only on FmxMBClass since traits cannot have a superclass.
  • Forbid to set two superclasses for the same class in a generator
  • Dead code removal
  • Simplification of the superclasses management
  • Make FmxMBImportingContext a subclass of FmxMBClass and remove duplicated code
  • I did some optimizations. Now it take 2second in Pharo 13 to generate all metamodels without a change and it will take 1.2sec in Pharo 14
  • Rename #classGeneralization to #superclass
  • Do not mix real objects and FmxMBClass in FmaxMBClass>>superclass
  • Groups do not need to be part of the MM

Future works

Following this change, there is still some work to do:

  • Add class comments
  • Add tests (I discovered that some features never tested the generated code but only the Ring model which is useless if we do not test the code we end up using)
  • Use singular/plurialize project everywhere in the builder instead of a manual implementation
  • The remote generator does not check for code that was generated but that should be removed. We should fix that

jecisc added 30 commits April 13, 2026 22:25
… it returns ring elements, not real classes...)
This makes some code a little more complex, but this code should vanish when we finish to cut the dependency to ring
…any impact until the end of the collection in order to manage removals later
@jecisc

jecisc commented May 11, 2026

Copy link
Copy Markdown
Member Author

This PR should now be done.

There are still work to do but I'll not have the time to do it now I think.

Maybe I'll find some personal time to fix the last bug I detected that is that remote methods are not removed. But the PR can be reviewed and merged now

jecisc added 7 commits May 11, 2026 12:50
This is fixed via an update of Fame but I'm adding a regression test in Famix
This will simplify the fact that multiple visitors (for multiple languages) will be able to visit the same entities without a clash
…els and to avoid double visit of some traits
@jecisc
jecisc merged commit 8662232 into moosetechnology:development May 28, 2026
15 of 16 checks passed
@jecisc
jecisc deleted the remove-ring branch May 28, 2026 13:15
@NicolasAnquetil

Copy link
Copy Markdown
Contributor

merci pour la review Clotilde

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants