phax / jcodemodel

A heavily extended fork of the com.sun.codemodel (from 2013/09)
Other
93 stars 34 forks source link

Allow direct import #52

Closed sinuhepop closed 5 years ago

sinuhepop commented 7 years ago

Sometimes is useful to be able to write code directly from a user specified String, and JDirectClass.directClass(String) is a great example of that. But in this case we must provide a fully qualified name for that type, and this is something we maybe don't know at that time, but it could compile because of user defined import definitions. So, I think a method like JCodeModel._import(String definition, boolean isStatic) would be very useful. Some examples:

myClass._import("java.util.*", false);
myClass._import("java.lang.Math.PI", true);
phax commented 7 years ago

For static imports it is clear. Do you search something for "grouping imports" (java.util.*) or do you have any other reason as well?

sinuhepop commented 7 years ago

I think it's better if I explain my current need as an example. I'm creating a type safe template library where templates are compiled to Java classes, just like JSP. In templates, types could be unqualified, but in configuration users should specify import of classes and packages.

Imagine a template like this:

<def name="myTemplate" params="Random r">
    <print content="r.nextInt()"/>
</def>

And this configuration:

config.addImport("java.util.stream.*");
config.addImport("java.util.*");

Then, generated class must be something like:

package folder.where.template.is;

import java.util.stream.*;
import java.util.*;

public class MyTemplate {
    public void run(Random r) {
        System.out.println(r.nextInt());
    }
}

For Random class I could look if java.util.stream.Random exists, then java.util.Random, and so on. But types are usually not created when I compile templates to Java, so it's not an option. IMHO, as JCodeModel allows arbitrary type names from String (qualified or not), it should allow direct import declarations, too. What do you think about it?

phax commented 7 years ago

Okay, makes sense. In this scenario explicitly stating imports sounds reasonable :)

phax commented 7 years ago

I looked into the code, and that doesn't look very promising at first sight - I'll check after Easter..

sinuhepop commented 7 years ago

I understand. In fact, I looked into the code before asking, and I must admit I don't know where to start.

Thanks for your time.

phax commented 7 years ago

The source is at JFormatter.ImportedClasses

sinuhepop commented 7 years ago

Mmm, ok. I'll take a look;

sviperll commented 7 years ago

Not an answer to your original question, but maybe you can take a look at my type-safe templating engine: https://github.com/sviperll/static-mustache . It is implemented as an annotation processor and generates Java classes for each template.

sinuhepop commented 7 years ago

@sviperll I didn't know about your project. Sounds interesting. I thought about doing it with APT, but I found it too difficult and it could lead to performance problems. Did you encounter any of these? I'll give a try.

sviperll commented 7 years ago

@sinuhepop I think there are no performance problems. The only problem I know of (but it can be a serious one) is that it doesn't always works predictably with incremental compilation as performed by gradle or maven. If you modify template-file only, but don't touch Java-source files than you will need to force full recompilation to actually get generated template implementation to be regenerated according to template-file change.

thedownup commented 5 years ago

how to import

phax commented 5 years ago

@thedownup when using codemodel.ref (Class<?>) that class is imported automatically. So there is no explit "import" method. hth

thedownup commented 5 years ago

Can you tell me how to achieve like List<List<String>> lists ? thank you

phax commented 5 years ago
    final JCodeModel codeModel = new JCodeModel ();
    final AbstractJClass aList = codeModel.ref (List.class);
    final JNarrowedClass cls = aList.narrow (aList.narrow (codeModel.ref (Integer.class)));
    assertEquals ("List<List<Integer>>", cls.name ());
stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.