in src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java [226:337]
private void addMopMethods(final InnerClassNode node) {
final boolean isStatic = isStatic(node);
final ClassNode outerClass = node.getOuterClass();
final int outerClassDistance = getObjectDistance(outerClass);
final String classInternalName = BytecodeHelper.getClassInternalName(node);
final String outerClassInternalName = getInternalName(outerClass, isStatic);
final String outerClassDescriptor = getTypeDescriptor(outerClass, isStatic);
addMissingHandler(node,
"methodMissing",
ACC_PUBLIC,
OBJECT_TYPE,
params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")),
(methodBody, parameters) -> {
if (isStatic) {
setMethodDispatcherCode(methodBody, classX(outerClass), parameters);
} else {
methodBody.addStatement(
new BytecodeSequence(new BytecodeInstruction() {
@Override
public void visit(final MethodVisitor mv) {
getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$invoke$" + outerClassDistance, "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitInsn(ARETURN);
}
})
);
}
}
);
addMissingHandler(node,
"$static_methodMissing",
ACC_PUBLIC | ACC_STATIC,
OBJECT_TYPE,
params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "args")),
(methodBody, parameters) -> {
setMethodDispatcherCode(methodBody, classX(outerClass), parameters);
}
);
addMissingHandler(node,
"propertyMissing",
ACC_PUBLIC,
VOID_TYPE,
params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "value")),
(methodBody, parameters) -> {
if (isStatic) {
setPropertySetterDispatcher(methodBody, classX(outerClass), parameters);
} else {
methodBody.addStatement(
new BytecodeSequence(new BytecodeInstruction() {
@Override
public void visit(final MethodVisitor mv) {
getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$set$" + outerClassDistance, "(Ljava/lang/String;Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
}
})
);
}
}
);
addMissingHandler(node,
"$static_propertyMissing",
ACC_PUBLIC | ACC_STATIC,
VOID_TYPE,
params(param(STRING_TYPE, "name"), param(OBJECT_TYPE, "value")),
(methodBody, parameters) -> {
setPropertySetterDispatcher(methodBody, classX(outerClass), parameters);
}
);
addMissingHandler(node,
"propertyMissing",
ACC_PUBLIC,
OBJECT_TYPE,
params(param(STRING_TYPE, "name")),
(methodBody, parameters) -> {
if (isStatic) {
setPropertyGetterDispatcher(methodBody, classX(outerClass), parameters);
} else {
methodBody.addStatement(
new BytecodeSequence(new BytecodeInstruction() {
@Override
public void visit(final MethodVisitor mv) {
getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$get$" + outerClassDistance, "(Ljava/lang/String;)Ljava/lang/Object;", false);
mv.visitInsn(ARETURN);
}
})
);
}
}
);
addMissingHandler(node,
"$static_propertyMissing",
ACC_PUBLIC | ACC_STATIC,
OBJECT_TYPE,
params(param(STRING_TYPE, "name")),
(methodBody, parameters) -> {
setPropertyGetterDispatcher(methodBody, classX(outerClass), parameters);
}
);
}