Hi Remi

On 05/20/2017 11:09 PM, Remi Forax wrote:
Hi Joe,
we had the same issue with ASM, we solve it without trying to detect every 
corner cases but by just comparing the number of parameter from the descriptor 
and the number of parameter (type?) annotations,
if there are less annotations, we add fake annotations at the starts of the 
array [1].

I don't remember the exact details but i'm pretty sure that at some point in 
the past ecj (the eclipse compiler) was generating more than one reference if 
you had an anonymous class inside an anonymous class.

ASM reports a special fake annotation "Ljava/lang/Synthetic;" so users can see 
that this is a synthetic parameter but i don't think it's a good idea to do that in the 
reflection API, ASM is more low level.

cheers,
Rémi

[1] 
http://websvn.ow2.org/filedetails.php?repname=asm&path=%2Ftrunk%2Fasm%2Fsrc%2Forg%2Fobjectweb%2Fasm%2FClassReader.java,
 in method readParameterAnnotations().
// ... This work-around supposes that the synthetic parameters are the first ones.
        int synthetics = Type.getArgumentTypes(context.desc).length - n;

Not always for local and anonymous classes. Captured values are appended to the parameter list. Source-level parameters are therefore between the outer instance and the captured values.

And if local or anonymous class is in the static context, there's no outer instance parameter, just captured values which are appended.

Here's what I was trying to do but then I found that local and anonymous classes never have STATIC modifier even if they are from static context:

http://cr.openjdk.java.net/~plevart/jdk9-dev/8074977_ConstructorParameterAnnotations/webrev.01/

If there was a reliable way to determine whether a local or anonymous class is from static context or not, then this could work for javac generated code at least.

Regards, Peter

----- Mail original -----
De: "Peter Levart" <peter.lev...@gmail.com>
À: "joe darcy" <joe.da...@oracle.com>, "core-libs-dev" 
<core-libs-dev@openjdk.java.net>
Envoyé: Samedi 20 Mai 2017 20:00:25
Objet: Re: JDK 9 RFR of JDK-8074977: Constructor.getAnnotatedParameterTypes 
returns wrong value
Hi Joe,

So enum classes, anonymous classes and local classes don't have a
standard way of passing synthetic/implicit constructor parameters? Do
various compilers do it differently than javac?

It's unfortunate but if # of parameter annotations arrays is less than
the # of parameters, Parameter.getAnnotations() may return wrong
annotations or throw IndexOutOfBoundException for enums, anonymous and
local classes. Can't we do anything for them? At least for code compiled
by javac?

For example, javac compiles enum classes so that they always prefix
constructor source parameters with a pair of (String name, int ordinal,
...) and so do anonymous enum subclasses provided by enum constants
(i.e. clazz.isAnonymousClass() && clazz.getSuperclass().isEnum())

Non-static local classes are compiled so that constructor source
parameters are prefixed with a single parameter (OuterClass
outerInstance, ...), while any captured variables follow source parameters

Static local classes are compiled so that constructor source parameters
come 1st, followed by any captured variables.

etc...

Regards, Peter


On 05/19/2017 11:31 PM, joe darcy wrote:
Hello,

Please review the webrev to fix

     JDK-8074977: Constructor.getAnnotatedParameterTypes returns wrong
value
     http://cr.openjdk.java.net/~darcy/8074977.3/

To condense a complicated situation, there are cases where the number
of parameters present for a constructor in source code and the number
of parameters present for that constructor in the class file differ.
One of those cases occurs for the constructor of a non-static member
class [1] where there is a leading parameter to accept the outer this
argument.

Bug JDK-8074977 reports on a situation where the type annotations on
constructor parameters are incorrectly reported. Essentially, an
off-by-one error is the cause since the annotation information is
stored with respect to the number of parameters present in the source
and an additional parameter is present at runtime.

An analogous situation exists for declaration annotations and
constructor parameters, declaration annotations being the traditional
flavor of annotations.

Type annotations and declaration annotations are read using different
APIs so require separate fixes to detect the additional parameter and
make the necessary adjustments in the returned information.

The regression tests cover both the type annotation reading API and
the two ways of reading declaration annotations on parameters, calling
getParameterAnnotations on the constructor or call getParameters on
the constructor and then calling getAnnotations on each parameter. The
getParameters API was added in JDK 8.

Static member and non-static member classes are used as test cases, as
are constructors with and without generic type information.

Thanks,

-Joe

[1]
https://blogs.oracle.com/darcy/nested,-inner,-member,-and-top-level-classes

Reply via email to