Array types of mirrored classes not translate

olsok
2007-09-04
2013-04-23
  • olsok
    olsok
    2007-09-04

    I tried to create a mirror class for EnumSet (based on the implementation in the competitor project Retrotranslator) and discovered that RetroWeaver is not translating (some?) (all?) array type references to mirrored classes. When the test case below is processed with "verify=true", one gets the error message: [retroweaver] com.XXX.tests.EnumArrayTest: unknown class java.lang.Enum

    public class EnumArrayTest extends TestCase {
        private static enum Day {
            SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
        }
        public void testAllOf() {
            Set<Day> days = allOf(Day.class);
            assertEquals(7, days.size());
            assertContent(days, Day.values());
        }
        public static <E extends Enum<E>> Set<E> allOf(Class<E> elementType) {
            Set<E> result = new HashSet();
            for (E e : elementType.getEnumConstants()) {  // <== The problematic line due to return of E[]
                result.add(e);
            }
            return result;
        }
        private void assertContent(Set<Day> set, Day... days) {
            assertEquals(days.length, set.size());
            List<Day> list = Arrays.asList(days);
            for (Day day : Day.values()) {
                if (list.contains(day)) {
                    assertTrue(set.contains(day));
                } else {
                    assertFalse(set.contains(day));
                }
            }
        }
    }

    I found two ways to work around this issue:
    1) To avoid use of an array type of a mirrored class, so replace the for loop above with:
            Object[] enumConstants = elementType.getEnumConstants();
            for (int i = 0; i < enumConstants.length; i++) {
                E e = (E)enumConstants[i];
                result.add(e);
            }
    2) Update RetroWeaver so that when lookup up class names that may potentially be array types, the underlying class name is used. This required changes to handle this case by using getClassMirrorTranslationDescriptor instead of getClassMirrorTranslation in the following places:
        RetroWeaver.java, method: visitLdcInsn
                // OLSOK 04-Sep-07 translate array references to mirrored classes
                s = NameTranslator.getGeneralTranslator().getClassMirrorTranslationDescriptor(s);
                s = NameTranslator.getStringBuilderTranslator().getClassMirrorTranslationDescriptor(s);
    //            s = NameTranslator.getGeneralTranslator().getClassMirrorTranslation(s);
    //            s = NameTranslator.getStringBuilderTranslator().getClassMirrorTranslation(s);
        NameTranslatorClassVisitor.java, methods: MethodTranslator.visitTypeInsn
            public void visitTypeInsn(final int opcode, final String desc) {
                // OLSOK 04-Sep-07 translate array references to mirrored classes
                super.visitTypeInsn(opcode, translator.getClassMirrorTranslationDescriptor(desc));
    //            super.visitTypeInsn(opcode, translator.getClassMirrorTranslation(desc));
            }

    and in NameTranslatorClassVisitor.java, method: MethodTranslator.visitMethodInsn adjusting the
        translator.getMirror call so that its argument strips off leading '[' leaving only the
        raw classname, not the array bounds delimiters.
                // OLSOK 04-Sep-07 translate array references to mirrored classes
                String lookupOwner = owner;
                while (lookupOwner.startsWith("[")) {
                    lookupOwner = lookupOwner.substring(1);
                }
                final Mirror mirror = translator.getMirror(lookupOwner);
    //            final Mirror mirror = translator.getMirror(owner);

    Could you please verify the changes outlined in (2) and (if correct) incorporate them into a future update of RetroWeaver? These three locations appeared when I instrumented NameTranslator.getMirror() to detect invocations where the class_ parameter began with '['.

     
    • Toby Reyelts
      Toby Reyelts
      2007-09-25

      Hi Olsok,

      That's definitely a bug and your changes look more or less correct. We'll absolutely make sure to get this into a future release.

      Thanks,
      -Toby

       
    • As Toby indicated, that's definitely a bug. I've merged your changes in the current code and it's now in the svn repository.

      I'll try to generate a new version with this fix and others in the next few days, most likely this week-end.

      Xavier