Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
-
None
-
None
Description
I think this is related to GROOVY-6899. I've been trying to isolate this for some time now: https://github.com/groovy/groovy-eclipse/issues/174. When using a generic array type as a return value, the bridge method is written improperly.
public interface MultiIndexed<PK, SK> { PK getPrimaryKey(); SK[] getSecondaryKeys(); } class MIData implements MultiIndexed<Integer, String> { final String value final Integer primaryKey final String[] secondaryKeys MIData(String val, Integer pk, String... sk) { this.value = val this.primaryKey = pk this.secondaryKeys = sk } }
javap on MiData.class shows public final SK[] getSecondaryKeys();. The equivalent Java class shows a different signature for the bridge method: public java.lang.Object[] getSecondaryKeys();.
This causes an NPE under Introspector when bean info is trying to be resolved.
java.lang.NullPointerException at com.sun.beans.TypeResolver.resolve(TypeResolver.java:203) at com.sun.beans.TypeResolver.resolve(TypeResolver.java:162) at com.sun.beans.TypeResolver.resolveInClass(TypeResolver.java:81) at java.beans.FeatureDescriptor.getReturnType(FeatureDescriptor.java:370) at java.beans.Introspector.getTargetEventInfo(Introspector.java:1052) at java.beans.Introspector.getBeanInfo(Introspector.java:427) at java.beans.Introspector.getBeanInfo(Introspector.java:173) at groovy.lang.MetaClassImpl$15.run(MetaClassImpl.java:3289) at java.security.AccessController.doPrivileged(Native Method) at groovy.lang.MetaClassImpl.addProperties(MetaClassImpl.java:3287) at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:3263) at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:254) at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:285) at MiData.$getStaticMetaClass(MiData.groovy) at MiData.<init>(MiData.groovy) class Main { static void main(String[] args) { def data = new MIData('V', 1, 'B') print 'no error' } }
I think this can be fixed in Verifier.getCovariantImplementation, like this:
// if we reach this point we have at least one parameter or return type, that // is different in its specified form. That means we have to create a bridge method! MethodNode newMethod = new MethodNode( oldMethod.getName(), overridingMethod.getModifiers() | ACC_SYNTHETIC | ACC_BRIDGE, // GRECLIPSE edit //oldMethod.getReturnType().getPlainNodeReference(), GenericsUtils.nonGeneric(oldMethod.getReturnType()), // GRECLIPSE end cleanParameters(oldMethod.getParameters()), oldMethod.getExceptions(), null );