[forge-issues] [JBoss JIRA] (FORGE-678) forge-parser-java: JavaClassImpl with generic super type produces wrong code

fiorenzo pizza (JIRA) jira-events at lists.jboss.org
Tue Oct 9 20:32:02 EDT 2012


    [ https://issues.jboss.org/browse/FORGE-678?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12725151#comment-12725151 ] 

fiorenzo pizza commented on FORGE-678:
--------------------------------------

THIS IS A LITTLE BRAINSTORMING AFTER MY RESEARCH... 
if my assumptions are correct,  I WILL CREATE A BRANCH CODE FOR A PULL REQUEST.
-----------------------------------------
-----------------------------------------

After a lot of search (for me, AST is very badly documented!!), i created the following use case.

My goal is to create this java class:
-----------------------------------------
package test1;
public class E<T> extends F<T> {
  public boolean foo(){
  }
}
-----------------------------------------
-----------------------------------------
I created a java project without forge inside:
-----------------------------------------

import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeParameter;

public class ASTClassCreatorWithGenericsExtensions
{
   public static void main(String[] args)
   {
      AST ast = AST.newAST(AST.JLS3);
      CompilationUnit unit = ast.newCompilationUnit();
      PackageDeclaration packageDeclaration = ast.newPackageDeclaration();
      packageDeclaration.setName(ast.newSimpleName("test1"));
      unit.setPackage(packageDeclaration);
      TypeParameter tp2 = ast.newTypeParameter();
      tp2.setName(ast.newSimpleName("T"));

      TypeDeclaration td = ast.newTypeDeclaration();
      td.setName(ast.newSimpleName("E"));
      td.typeParameters().add(tp2);
      ParameterizedType PT1 = ast.newParameterizedType(ast.newSimpleType(ast.newSimpleName("F")));
      PT1.typeArguments().add(ast.newSimpleType(ast.newSimpleName("T")));
      td.setSuperclassType(PT1);
      Modifier mod = ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD);
      td.modifiers().add(mod);
      unit.types().add(td);
      
      MethodDeclaration md = ast.newMethodDeclaration();
      md.setName(ast.newSimpleName("foo"));
      md.setReturnType2(ast.newPrimitiveType(PrimitiveType.BOOLEAN));
      mod = ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD);
      md.modifiers().add(mod);
      Block block = ast.newBlock();
      md.setBody(block);
      td.bodyDeclarations().add(md);
      System.out.println(unit);
   }
}
-----------------------------------------
-----------------------------------------
-----------------------------------------
using that example code, we should modify the method setSuperType in the class org.jboss.forge.parser.spi.JavaParserImpl :
-----------------------------------------

@Override
   public JavaClass setSuperType(final String type)
   {
      if (Types.isGeneric(type))
      {
         String typeD = Types.stripGenerics(type);
         String typeP = Types.getGenericsTypeArgument(type);
         org.eclipse.jdt.core.dom.ParameterizedType pt = body.getAST().newParameterizedType(
                  body.getAST().newSimpleType(body.getAST().newSimpleName(typeD)));
         pt.typeArguments().add(body.getAST().newSimpleType(body.getAST().newSimpleName(typeP)));
         getBodyDeclaration().setStructuralProperty(TypeDeclaration.SUPERCLASS_TYPE_PROPERTY, pt);

         if (!hasImport(typeD) && Types.isQualified(typeD))
         {
            addImport(typeD);
         }
         if (!hasImport(typeP) && Types.isQualified(typeP))
         {
            addImport(typeP);
         }
      }
      else
      {
         SimpleType simpleType = body.getAST().newSimpleType(body.getAST().newSimpleName(Types.toSimpleName(type)));
         getBodyDeclaration().setStructuralProperty(TypeDeclaration.SUPERCLASS_TYPE_PROPERTY, simpleType);

         if (!hasImport(type) && Types.isQualified(type))
         {
            addImport(type);
         }
      }

      return this;
   }
-------------------------------------------------------
I also added to org.jboss.forge.parser.java.util.Types this new method:

public static String getGenericsTypeArgument(final String type)
   {
      return getGenerics(type).replaceAll("<", "").replaceAll(">", "");
   }
-------------------------------------------------------

What do you think about my solution?




                
> forge-parser-java: JavaClassImpl with generic super type produces wrong code 
> -----------------------------------------------------------------------------
>
>                 Key: FORGE-678
>                 URL: https://issues.jboss.org/browse/FORGE-678
>             Project: Forge
>          Issue Type: Bug
>          Components: Parsers / File Manipulation
>    Affects Versions: 1.0.6.Final
>            Reporter: fiorenzo pizza
>              Labels: annoying
>
> forge doesn't support correctly generics.
> some use case, improperly parsed:
> JavaClass c1 = JavaParser.parse(JavaClass.class, "package it.coopservice.test; public class Bar<T> {}");
>       JavaClass javaClass = JavaParser.create(JavaClass.class);
>       javaClass.setName("TBarTest");
>       javaClass.setSuperType(c1);
>       javaClass.setPackage("it.coopservice.test");
>       javaClass.addImport("it.coopservice.test.Bar");
> produces:
> public class TBarTest extends Bar{}
> and this:
> JavaClass c0 = JavaParser.parse(JavaClass.class, "package it.coopservice.test; public class Foo {}");
>       JavaClass c1 = JavaParser.parse(JavaClass.class, "package it.coopservice.test; public class Bar<Foo> {}");
>       JavaClass javaClass = JavaParser.create(JavaClass.class);
>       javaClass.setName("FooBarDirectTest");
>       javaClass.setPackage("it.coopservice.test");
>       javaClass.addImport("it.coopservice.test.Bar");
>       javaClass.addImport("it.coopservice.test.Foo");
>       javaClass.setSuperType("Bar<Foo>");
> produces:
> java.lang.IllegalArgumentException
> my complete test code and output:
> https://gist.github.com/3746475

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira


More information about the forge-issues mailing list