final String outerClassDescriptor = getTypeDescriptor(outerClass, isStatic);
final int objectDistance = getObjectDistance(outerClass);
// add method dispatcher
Parameter[] parameters = new Parameter[]{
new Parameter(ClassHelper.STRING_TYPE, "name"),
new Parameter(ClassHelper.OBJECT_TYPE, "args")
};
String methodName = "methodMissing";
if (isStatic)
addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
MethodNode method = node.addSyntheticMethod(
methodName,
Opcodes.ACC_PUBLIC,
ClassHelper.OBJECT_TYPE,
parameters,
ClassNode.EMPTY_ARRAY,
null
);
BlockStatement block = new BlockStatement();
if (isStatic) {
setMethodDispatcherCode(block, new ClassExpression(outerClass), parameters);
} else {
block.addStatement(
new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
getThis(mv,classInternalName,outerClassDescriptor,outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$invoke$" + objectDistance, "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitInsn(ARETURN);
}
})
);
}
method.setCode(block);
// add property getter dispatcher
parameters = new Parameter[]{
new Parameter(ClassHelper.STRING_TYPE, "name"),
new Parameter(ClassHelper.OBJECT_TYPE, "val")
};
methodName = "propertyMissing";
if (isStatic)
addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
method = node.addSyntheticMethod(
methodName,
Opcodes.ACC_PUBLIC,
ClassHelper.VOID_TYPE,
parameters,
ClassNode.EMPTY_ARRAY,
null
);
block = new BlockStatement();
if (isStatic) {
setPropertySetterDispatcher(block, new ClassExpression(node.getOuterClass()), parameters);
} else {
block.addStatement(
new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
getThis(mv,classInternalName,outerClassDescriptor,outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$set$" + objectDistance, "(Ljava/lang/String;Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
}
})
);
}
method.setCode(block);
// add property setter dispatcher
parameters = new Parameter[]{
new Parameter(ClassHelper.STRING_TYPE, "name")
};
methodName = "propertyMissing";
if (isStatic)
addCompilationErrorOnCustomMethodNode(node, methodName, parameters);