Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are a couple of issues here. You can either be interested in knowing the Java type of the method invocation receiver or just knowing the class on the method is invoked. Java information is more informative as it gives you generic types as well, e.g. <code>List&lt;String&gt;</code> while Elements would only provide you with the class, e.g. <code>List&lt;E&gt;</code>.</p> <p><b>Getting the Element</b></p> <p>To get the Element of the class the method is invoked on, you can do the following:</p> <pre><code> MethodInvocationTree node = ...; Element method = TreeInfo.symbol((JCTree)node.getMethodSelect()); TypeElement invokedClass = (TypeElement)method.getEnclosingElement(); </code></pre> <p>Corner cases:</p> <p>1. invokedClass might be a superclass of the receiver type. So running the snippet on <code>new ArrayList&lt;String&gt;.equals(null)</code> would return <code>AbstractList</code> rather than <code>ArrayList</code>, since equals() is implemented in <code>AbstractList</code> not <code>ArrayList</code>.</p> <p>2. When handling array invocations, e.g. <code>new int[].clone()</code>, you would get <code>TypeElement</code> of class <code>Array</code>.</p> <p><b>Getting the actual type</b></p> <p>To get the type, there is no direct way for determining it what the receiver type is. There is some complexity in handling method invocations within inner classes where the receiver is not given explicitly (e.g. unlike <code>OuterClass.this.toString()</code>). Here is a sample implementation:</p> <pre><code> MethodInvocationTree node = ...; TypeMirror receiver; if (methodSel.getKind() == Tree.Kind.MEMBER_SELECT) { ExpressionTree receiver = ((MemberSelectTree)methodSel).getExpression(); receiverType = ((JCTree)receiver).type; } else if (methodSel.getKind() == Tree.Kind.IDENTIFIER) { // need to resolve implicit this, which is described in // JLS3 15.12.1 and 15.9.2 // A bit too much work that I don't want to work on now // Look at source code of // Attr.visitApply(JCMethodInvocation) // resolveImplicitThis(DiagnosticPosition, Env, Type) } else throw new AssertionError("Unexpected type: " + methodSel.getKind()); </code></pre> <p>Note:</p> <p>The <code>receiver</code> type needs to be <code>TypeMirror</code> not <code>DeclaredType</code> unfortunately. When calling <code>new int[5].clone()</code>, <code>receiver</code> would be an <code>ArrayType</code> of <code>int[]</code>, which is more informative than the previous method.</p> <p><b>Getting it to run</b></p> <p>Both of the previous methods require the compiler to resolve the type information for the classes. In usual circumstances, the compiler only resolve the types for method declarations but not the bodies. Hence, the methods described earlier would return <code>null</code> instead.</p> <p>To have the compiler resolve the type information, you can do one of the following ways:</p> <p>1. Use <code>AbstractTypeProcessor</code> class that just got added to the compiler repository for JDK 7. Check out the work on <a href="http://groups.csail.mit.edu/pag/jsr308/" rel="noreferrer">JSR 308</a> and their compiler. While the work is mainly on annotated types, it might be useful for. The compiler allows you to use the provided class in a backward compatible manner with Java 5.</p> <p>This approach allows you to write processors that get invoked just like your current processors.</p> <p>2. Use <code>JavacTask</code> instead and call <code>JavacTask.analyze()</code>. Look at the main method of <a href="http://hg.openjdk.java.net/jdk7/jdk7/langtools/file/6855e5aa3348/test/tools/javac/api/6557752/T6557752.java" rel="noreferrer">this javac test</a> to see how to invoke your visitor on the classes.</p> <p>This approach makes your processor look more like an analysis tool rather than a plug-in to the compiler, as you would need to invoke it directly rather than have it be a regular process.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload