Menu

get name and TypeParams on ParameterizedType

Developers
2008-07-19
2012-10-08
  • Thorsten Merten

    Thorsten Merten - 2008-07-19

    Hello,

    I'd like like to get the Type parameters for an object of ParameterizedType. If I call .get[Full]Name() I receive something like [java.util.]Map. But In Java5 it could be Map<String, Map<Integer, Float>>.

    To archieve this my first try was something like the example below. Anyways, the line marked as IMPOSSIBLE is the problem. Furthermore on a TypeArgument you can not call "getFullName()" as on "normal" types.

    Maybe/Hopefully there is some smarter way to do this I did not find...

    Well, here is the example function:

    /**
     * recursively creates the signature for parameterized types.
     * 
     * non recursive example:
     * Map&lt;String, String&gt;
     * =&gt; 1: &lt;String, String&gt;
     * where 1 is the stack position
     * 
     * recursive example:
     * Map&lt;String, Map&lt;Int, Float&gt;&gt;:
     * =&gt; 1: &lt;String,
     * =&gt; 2: &lt;Int, Float&gt; -&gt; return
     * =&gt; 1: &gt;
     * 
     * @param pt the parameterized type to create the signature from
     * @return the string created for the types e.g. &lt;String, &lt;Map&lt;Int, Float&gt;&gt;
     */
    private String createParameterizedSignature(ParameterizedType pt) {
        Iterator&lt;? extends TypeArgument&gt; iter = pt.getTypeArgs().iterator();
        String signature = pt.getName() + &quot;&lt;&quot;;
        while (iter.hasNext()) {
            TypeArgument ta = iter.next();
    
                        //IMPOSSIBLE
            if (ta instanceof ParameterizedType) {
                signature += ta.getTypeName();
                // if the inner type is parameterized -&gt; add the same string for this inner type again.
                signature += createParameterizedSignature((ParameterizedType) ta);
            } else {
                signature += ta.getTypeName();
            }
            if (iter.hasNext()) {
                signature += &quot;,&quot;;
            }
        }
        return signature + &quot;&gt;&quot;;
    }
    

    Thanks in advance for any help. Regards,
    Thorsten

     
    • Tobias Gutzmann

      Tobias Gutzmann - 2008-07-21

      Hej,

      the next release will have an appropriate method. However, it'll take some time until it comes out because the API has been changed in some core parts, and documentation is needed for that. Further, there're still a couple of bugs/issues that need to be resolved.

      In the upcoming release, each subtypes of ClassType implements a method String getFullSignature()

      This is the code called from all types inheriting from TypeArgument. Note that it should be rewritten to use StringBuilders for better performance, but it's not high priority right now (because the Recoder core itself doesn't use these methods).

          public static String getFullSignature(TypeArgument ta) { // common implementation for all subtypes
              String res;
              switch (ta.getWildcardMode()) {
              case None: res = &quot;&quot;; break;
              case Any: return &quot;?&quot;; // shortcut
              case Extends: res = &quot;? extends &quot;; break;
              case Super: res = &quot;? super &quot;; break;
              default: throw new Error(); // all possible cases are covered
              }
              res += ta.getTypeName();
              List&lt;? extends TypeArgument&gt; targs = ta.getTypeArguments();
              if (targs == null || targs.size() == 0)
                  return res;
              res +=&quot;&lt;&quot;;
              String delim = &quot;&quot;;
              for (TypeArgument ta_sub : ta.getTypeArguments()) {
                  res += delim;
                  res += ta_sub.getFullSignature();
                  delim = &quot;,&quot;;
              }
              res +=&quot;&gt;&quot;;
              return res;
          }
      

      In ParameterizedType:

      public String getFullSignature() {
          String res = getFullName() + &quot;&lt;&quot;;
          String del = &quot;&quot;;
          for (TypeArgument ta : getTypeArgs()) {
              res = res + del + ta.getFullSignature();
              del = &quot;,&quot;;
          }
          res = res + &quot;&gt;&quot;;
          return res;
      }
      

      Common implementation for TypeParameter:

          public static String getFullSignature(TypeParameter tp) {           
              String res = tp.getParameterName();
              String del = &quot; extends &quot;;
              for (int i = 0; i &lt; tp.getBoundCount(); i++) {
                  res += del;
                  res += tp.getBoundName(i);
                  List&lt;? extends TypeArgument&gt; tas = tp.getBoundTypeArguments(i);
                  if (tas != null &amp;&amp; tas.size() &gt; 0) {
                      res += &quot;&lt;&quot;;
                      String delim2 = &quot;&quot;;
                      for (TypeArgument ta : tas) {
                          res += delim2;
                          res += ta.getFullSignature();
                          delim2 = &quot;,&quot;;
                      }
                      res += &quot;&gt;&quot;;
                  }
                  del = &quot;,&quot;;
              }
              return res;
          }
      

      TypeDeclaration / ClassFile:

      public String getFullSignature() {
          String res = getFullName();
          ASTList&lt;TypeParameterDeclaration&gt; tps = getTypeParameters();
          if (tps == null || tps.size() == 0)
              return res;
          res += &quot;&lt;&quot;;
          String delim = &quot;&quot;;
          for (TypeParameterDeclaration tpd : tps) {
              res += delim;
              res += tpd.getFullSignature();
              delim = &quot;,&quot;;
          }
          res += &quot;&gt;&quot;;
          return res;
      }
      

      ... or just wait for the next release ;-)

      Best regards,

      Tobias

       
    • Thorsten Merten

      Thorsten Merten - 2008-07-23

      First of all thanks for the help - after shortly hitting the Sun Bug 6294779 I've been able to recompile Recoder with the needed Methods.

      I am not sure about what the JLS3 says but one more thing for just for completeness. If use getFullSignature() and getFullName() I can archive something like

      package.Class.myMethod(java.util.List<Tree>)

      It might be possible (at some time) to implement something like

      package.Class.myMethod(java.util.List<com.sun.tools.javac.tree.Tree>)
      package.Class.myMethod(java.util.List<sun.reflect.generics.tree.Tree>)
      (at least it would be kind of a different signature, IMHO)

      in this case the above would not be a enough for a unique description... Anyways, this is very - er - uncommon ;).

      Well, I thought about it because getFullName() on a class gives the whole package and getName() the name only.
      Maybe it is nice to adopt this behavior for get[Full]Signature().

      Again thanks for the solution.
      Cheers,
      Thorsten

       
    • Tobias Gutzmann

      Tobias Gutzmann - 2008-07-23

      Hej,

      In your example, the two methods myMethod() don't have the same signature but the same erasure, which causes a compile time error, cf. JLS 3rd edition, §8.4.8.3. However, Recoder might not always recognize this case, as type arguments are not completely taken into consideration when checking for method applicability - yet.
      And yes, the Java language has become much more complicated because of generics ;-)

      I'll add methods for getting the signature of methods as a string as fell and revise existing methods prior the next release to get a more consistent naming/behaviour of such methods. Every suggestion is welcome ;-)

      /Tobias

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.