cincheo / jsweet

A Java to JavaScript transpiler.
http://www.jsweet.org
Other
1.46k stars 158 forks source link

Possibility to tune the translated TypeScript enumerated type? #513

Closed edouardmercier closed 5 years ago

edouardmercier commented 5 years ago

I'm using Jsweet 2.2.0-SNAPSHOT.

As explained in the documentation, at https://github.com/cincheo/jsweet/blob/master/doc/jsweet-language-specifications.md#enums, JSweet translates the Java enumerated type into a simple TypeScript enumerated type.

Since TypeScript now offers "String enums", https://www.typescriptlang.org/docs/handbook/enums.html, it would be nice to be able to customize the translation behavior.

In my case, I would like to translate the following Java type:

public enum MyEnum
{
  Value1,
  Value2
}

into

enum MyEnum
{
  Value1 = "Value1",
  Value2 = "Value2"
}

I managed to do the trick by using this quick and ugly Jsweet factory:

package my.project;

import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import org.jsweet.transpiler.JSweetContext;
import org.jsweet.transpiler.JSweetFactory;
import org.jsweet.transpiler.Java2TypeScriptTranslator;
import org.jsweet.transpiler.TranspilationHandler;
import org.jsweet.transpiler.extension.PrinterAdapter;
import org.jsweet.transpiler.util.AbstractTreePrinter;

public final class MyJSweetFactory
    extends JSweetFactory
{

  @Override
  public Java2TypeScriptTranslator createTranslator(PrinterAdapter adapter, TranspilationHandler transpilationHandler,
      JSweetContext context, JCCompilationUnit compilationUnit, boolean fillSourceMap)
  {
    // This introduces an ugly hack which enables to assign values to enumerated types
    return new Java2TypeScriptTranslator(adapter, transpilationHandler, context, compilationUnit, fillSourceMap)
    {

      private JCVariableDecl lastEnumJcVariableDecl;

      public AbstractTreePrinter print(String string)
      {
        if (string.equals(", ") && lastEnumJcVariableDecl != null)
        {
          return super.print(" = \"" + lastEnumJcVariableDecl.getName() + "\"" + string);
        }
        else
        {
          return super.print(string);
        }
      }

      @Override
      public AbstractTreePrinter print(JCTree tree)
      {
        if (tree instanceof JCTree.JCVariableDecl)
        {
          lastEnumJcVariableDecl = (JCVariableDecl) tree;
        }
        else
        {
          lastEnumJcVariableDecl = null;
        }
        return super.print(tree);
      }

    };
  }

}

I could not find a more elegant way since the Java2TypeScriptTranslator.visitClassDef(JCClassDecl classdecl) does not seem to offer the required granularity.

What do you think of this requirement? Do you think that there is a better way to achieved this?

lgrignon commented 5 years ago

Hello, indeed that's an idea.

Why would you want this? Do you want a more readable TS code? Easier to read values at runtime?

Anyway, I think the best way would be to add a StringEnum annotation.

renaudpawlak commented 5 years ago

Have you read the documentation about extensions? You can start from the example I give here. Tell me it it would work for you.

renaudpawlak commented 5 years ago

Note: that does not match exactly what you need, but that could help to get started. It defines its own annotation.

edouardmercier commented 5 years ago

Thank you @lgrignon and @renaudpawlak for your insights. I have read very quickly the documentation what @renaudpawlak provided about the PrinterAdaptter: I will definitively take a careful look at it and will let you know whether it enables to achieve what I'm looking for.

lgrignon commented 5 years ago

@edouardmercier did you manage to do what you wanted? Could you close this issue if everything is fine by you please? Thanks :)

edouardmercier commented 5 years ago

@lgrignon, sorry the late answer. We haven't found the time to investigate so far, because it is not business critical anymore. I closed the issue and propose to reopen it if it becomes once again critical.