Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Templates in maps loaded via STGroupFile do not use registered ObjectModelAdaptors #223

Open
Aethon opened this issue Oct 2, 2019 · 5 comments

Comments

@Aethon
Copy link

Aethon commented Oct 2, 2019

Given ST4 4.1 on the JVM and the following code, I would expect that the View would be dumped out identically both times. However, the following is produced:

before template = View(regularName=HIP! HIP!,special_name=HUZZAH!) and after map template = View(regularName=HIP! HIP!,special_name=)

It seems that the templates in the map create a new group based on the file they appear in but this new group does not inherit the model adaptor registrations from the original group. Much confusion ensues.

import org.stringtemplate.v4.*
import org.stringtemplate.v4.misc.*
import java.nio.charset.StandardCharsets

class Adaptor : ObjectModelAdaptor() {
    override fun getProperty(interp: Interpreter, self: ST, o: Any, property: Any?, propertyName: String): Any? =
        if (propertyName == "special_name")
            "HUZZAH!"
        else
            super.getProperty(interp, self, o, property, propertyName)
}

class View(val regularName: String)

fun main(args: Array<String>) {
    val group = STGroupFile(View::class.java.getResource("/strepl/main.stg"), StandardCharsets.UTF_8.name(), '$', '$')
    group.registerModelAdaptor(Object::class.java, Adaptor())
    val st = group.getInstanceOf("main")
    st.add("view", View("HIP! HIP!"))
    println(st.render())
}

/strepl/main:

import "other.stg"

main(view) ::= "$other_main(view)$"

/strepl/other:

delimiters "$", "$"

other_main(view) ::= "before template = $dump(view)$ and after $map.(\"simple\")$"
map ::= [
    "simple": <%map template = $dump(view)$%>
]
dump(view) ::= "View(regularName=$view.regularName$,special_name=$view.special_name$)"
@Aethon
Copy link
Author

Aethon commented Oct 2, 2019

For anyone that finds this, the workaround I am using is to just store template names in the map and use double indirection to invoke them:

... $(map.(\"simple\"))()$ ...

and

map ::= [
    "simple": "simple_template"
]

simple_template() ::= "map template = $dump(view)$"

It is slightly more verbose, but not so terrible as workarounds go :)

@parrt
Copy link
Member

parrt commented Oct 5, 2019

hi. is this Kotlin? Might matter. E.g., what if an object gets wrapped and no longer a java object? Maybe the registration no longer works?

@Aethon
Copy link
Author

Aethon commented Oct 5, 2019

It is Kotlin. The registrations work, just not after "passing through" a mapped template in a loaded group file.

I will provide a Java repro after the weekend.

Thanks.

@parrt
Copy link
Member

parrt commented Oct 5, 2019

ok, yeah, Maybe there's something about parameter handoff or dynamic scoping that is screwing something up here.

@Aethon
Copy link
Author

Aethon commented Oct 6, 2019

Here is the Java 11 repro (using the same template files above):

package test;

import org.stringtemplate.v4.Interpreter;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroupFile;
import org.stringtemplate.v4.misc.ObjectModelAdaptor;

import java.nio.charset.StandardCharsets;

public class ST4BugReplJava {
    static class Adaptor extends ObjectModelAdaptor {
        @Override
        public Object getProperty(Interpreter interp, ST self, Object o, Object property, String propertyName) {
            if (propertyName.equals("special_name"))
                return "HUZZAH!";
            return super.getProperty(interp, self, o, property, propertyName);
        }
    }

    static class View {
        public String regularName;

        public View(String regularName) {
            this.regularName = regularName;
        }
    }

    static public void main(String[] args) {
        var group = new STGroupFile(View.class.getResource("/strepl/main.stg"), StandardCharsets.UTF_8.name(), '$', '$');
        group.registerModelAdaptor(Object.class, new Adaptor());
        var st = group.getInstanceOf("main");
        st.add("view", new View("HIP! HIP!"));
        System.out.println(st.render());
    }
}

@antlr antlr deleted a comment Apr 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants