Generating model-wide static methods class

Greetings to the MPS team!

I have a question regarding generation of Java code. The solution I found doesn't seem to work, and I don't know if it's an error on my part or in the MPS. Here are the details:

I want to be able to create a class that has only static methods to be used from other classes generated from the same model. E.g. the "static" class, named '__STATIC__' for example, would contain all model-wide initialization.

The obvious way to generate such a class would be by specifying a mapping rule with the static class template as the target, for which return the model root as the source node. Here's my code for doing just that:

    public static List templateMappingRule_SourceQuery_ModelRoot(ITemplateGenerator generator)  {
        ArrayList result = new ArrayList();
        SNode node = generator.getSourceModel().getModelDescriptor().getModelRoot();
        result.add(node);
        return result;    
    }

So far so good, but that's not all I require. I also need to add static methods into this class that would reflect all the static data in my source model. I attempted to employ an weaving rule for this task, specifying a node builder for the same model root as the context. Here's my code:

    public static INodeBuilder templateWeavingRule_Context_ModelRoot(SNode sourceNode, ITemplateGenerator generator) {
            SNode node = generator.getSourceModel().getModelDescriptor().getModelRoot();
            INodeBuilder nb = generator.findNodeBuilderForSource(node);
            return nb;
    }

Unfortunately, this doesn't work. On attempt to generate code from my model, the generation process goes into an infinite loop (see stacktrace below). Even if I put a sentry into my code that would block the infinite recursion, the generation fails, despite correct node builder instance returned from my code.

What am I doing wrong? Is there other way to achieve the same result that I require?

Thanks a lot.

Here's the stacktrace of the infinite loop.

        at qlog.generator.baseLanguage.template.main.Queries.templateWeavingRule_Context_ModelRoot(Queries.java:87)
        at sun.reflect.GeneratedMethodAccessor166.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at jetbrains.mps.util.QueryMethod.invoke(QueryMethod.java:109)
        at jetbrains.mps.generator.template.TemplateGenUtil.getContextNodeBuilderForWeavingingRule(TemplateGenUtil.java:303)
        at jetbrains.mps.generator.template.TemplateGenUtil.applyWeavingingRule(TemplateGenUtil.java:201)
        at jetbrains.mps.generator.template.DefaultNodeBuilderManager.createRootBuilders(DefaultNodeBuilderManager.java:114)
        at jetbrains.mps.generator.template.AbstractNodeBuilderManager.getRootBuilders(AbstractNodeBuilderManager.java:41)
        at jetbrains.mps.generator.template.AbstractTemplateModelGenerator.findNodeBuilderForSource(AbstractTemplateModelGenerator.java:332)
        at qlog.generator.baseLanguage.template.main.Queries.templateWeavingRule_Context_ModelRoot(Queries.java:87)
        at sun.reflect.GeneratedMethodAccessor166.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at jetbrains.mps.util.QueryMethod.invoke(QueryMethod.java:109)
        at jetbrains.mps.generator.template.TemplateGenUtil.getContextNodeBuilderForWeavingingRule(TemplateGenUtil.java:303)
        at jetbrains.mps.generator.template.TemplateGenUtil.applyWeavingingRule(TemplateGenUtil.java:201)
        at jetbrains.mps.generator.template.DefaultNodeBuilderManager.createRootBuilders(DefaultNodeBuilderManager.java:114)
        at jetbrains.mps.generator.template.AbstractNodeBuilderManager.getRootBuilders(AbstractNodeBuilderManager.java:41)
        at jetbrains.mps.generator.template.AbstractTemplateModelGenerator.findNodeBuilderForSource(AbstractTemplateModelGenerator.java:332)
        at qlog.generator.baseLanguage.template.main.Queries.templateWeavingRule_Context_ModelRoot(Queries.java:87)
        at sun.reflect.GeneratedMethodAccessor166.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at jetbrains.mps.util.QueryMethod.invoke(QueryMethod.java:109)
        at jetbrains.mps.generator.template.TemplateGenUtil.getContextNodeBuilderForWeavingingRule(TemplateGenUtil.java:303)
        at jetbrains.mps.generator.template.TemplateGenUtil.applyWeavingingRule(TemplateGenUtil.java:201)
        at jetbrains.mps.generator.template.DefaultNodeBuilderManager.createRootBuilders(DefaultNodeBuilderManager.java:114)
        at jetbrains.mps.generator.template.AbstractNodeBuilderManager.getRootBuilders(AbstractNodeBuilderManager.java:41)
        at jetbrains.mps.generator.template.AbstractTemplateModelGenerator.findNodeBuilderForSource(AbstractTemplateModelGenerator.java:332)
        at qlog.generator.baseLanguage.template.main.Queries.templateWeavingRule_Context_ModelRoot(Queries.java:87)
 

Cheers,

Fedor.

0
3 comments

Hi Fedor!

Thanks for feedback!

I've made all generator' methods findNodeBuilderXXX() safe to call form inside the generator queries.

I've also added conditional root rules which are more suitable for your purpose then mapping rules.

igor.

0

I've also deprecated the method

INodeBuilder findNodeBuilderForSource(SNode sourceNode) in ITemplateGenerator

the best way to find a builder is to use

findNodeBuilderForSource(SNode sourceNode, String mappingName)

any mapping rule or macro in MPS can be tagged with a textual label (mappingName) so that later, using this method, you can find builder created for that place in templates.

another way is to use

findNodeBuilderForSource(SNode sourceNode, Condition<INodeBuilder> condition)but this is not as efficient as first one.

0

Thanks, Igor.

The method you've deprecated:

    INodeBuilder findNodeBuilderForSource(SNode sourceNode) 

-- is behaving strangely and unpredictably. I was forced to switch to one of the alternatives, as my generation was working very unstable.

0

Please sign in to leave a comment.