@Override public Statement resolve(DotNode dotNode) { Class<?> lhsType = dotNode.getLhs().getDataType().getReturnedClass(); // ensure the attribute is available as a field of the comparator String attrVarName = dotNode.getPath().replace('.', '_') + "_attr"; if (containingClass != null && !generatedClassVariables.contains(attrVarName)) { generatedClassVariables.add(attrVarName); containingClass.privateField(attrVarName, ErraiAttribute.class) .modifiers(Modifier.Final) .initializesWith( Stmt.nestedCall(new StringStatement("entityManager.getMetamodel()", MetaClassFactory.get(ErraiMetamodel.class))) .invoke("entity", Stmt.loadLiteral(lhsType)) .invoke("getAttribute", dotNode.getPropertyPath())) .finish(); } // XXX need a StringStatement here because codegen can't see fields of anonymous inner classes. (ERRAI-363) return Stmt.nestedCall(new StringStatement(attrVarName, MetaClassFactory.get(ErraiAttribute.class))) .invoke("get", Stmt.loadVariable(variableName)); } }
/** Regression test for ERRAI-363. */ @Test public void testReferenceToAnonymousClassMember() throws Exception { ClassStructureBuilder<?> builder = ClassBuilder.define("com.foo.A").publicScope().body(); builder.privateMethod(void.class, "method") .append(ObjectBuilder.newInstanceOf(Runnable.class).extend() .privateField("memberOfRunnable", Object.class).finish() .publicOverridesMethod("run").append(Stmt.loadVariable("memberOfRunnable").invoke("hashCode")).finish() .finish()) .finish(); String javaString = builder.toJavaString(); assertEquals("package com.foo; public class A { private void method() { new Runnable() { private Object memberOfRunnable; public void run() { memberOfRunnable.hashCode(); } }; } }", javaString); }