List of usage examples for org.objectweb.asm.tree ClassNode visitField
@Override public FieldVisitor visitField(final int access, final String name, final String descriptor, final String signature, final Object value)
From source file:nova.core.wrapper.mc.forge.v17.asm.lib.ComponentInjector.java
License:Open Source License
private Class<? extends T> construct(List<Class<? extends Component>> components) { // Map components to specified wrapped interfaces Map<Class<?>, Class<? extends Component>> intfComponentMap = new HashMap<>(); for (Class<? extends Component> component : components) { for (Passthrough pt : component.getAnnotationsByType(Passthrough.class)) { Class<?> intf;/* w ww. j ava 2s. co m*/ try { intf = Class.forName(pt.value()); } catch (ClassNotFoundException exec) { throw new ClassLoaderUtil.ClassLoaderException( "Invalid passthrough \"%s\" on component %s, the specified interface doesn't exist.", pt.value(), component); } if (!intf.isAssignableFrom(component)) { throw new ClassLoaderUtil.ClassLoaderException( "Invalid passthrough \"%s\" on component %s, the specified interface isn't implemented.", pt.value(), component); } if (intfComponentMap.containsKey(intf)) { throw new ClassLoaderUtil.ClassLoaderException( "Duplicate Passthrough interface found: %s (%s, %s)", pt.value(), component, intfComponentMap.get(intf)); } intfComponentMap.put(intf, component); } } // Create new ClassNode from cached bytes ClassNode clazzNode = new ClassNode(); String name = Type.getInternalName(baseClazz); String classname = name + "_$$_NOVA_" + cache.size(); // Inject block field clazzNode.visit(V1_8, ACC_PUBLIC | ACC_SUPER, classname, null, name, intfComponentMap.keySet().stream().map(Type::getInternalName).toArray(s -> new String[s])); clazzNode.visitField(ACC_PRIVATE | ACC_FINAL, "$$_provider", Type.getDescriptor(ComponentProvider.class), null, null).visitEnd(); // Add constructors for (Constructor<?> constructor : baseClazz.getConstructors()) { int mod = constructor.getModifiers(); String descr = Type.getConstructorDescriptor(constructor); if (Modifier.isFinal(mod) || Modifier.isPrivate(mod)) { continue; } MethodVisitor mv = clazzNode.visitMethod(mod, "<init>", descr, null, ASMHelper.getExceptionTypes(constructor)); // Call super constructor mv.visitCode(); // load this mv.visitVarInsn(ALOAD, 0); Class<?>[] parameters = constructor.getParameterTypes(); for (int i = 0; i < constructor.getParameterCount(); i++) { // variables mv.visitVarInsn(Type.getType(parameters[i]).getOpcode(ILOAD), i + 1); } mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(baseClazz), "<init>", descr, false); // return mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } // Add methods for (Class<?> intf : intfComponentMap.keySet()) { // Create class constant Type clazzConst = Type.getType(intf.getClass()); for (Method m : intf.getMethods()) { boolean isVoid = m.getReturnType() == null; String descr = Type.getMethodDescriptor(m); MethodVisitor mv = clazzNode.visitMethod(ACC_PUBLIC, m.getName(), descr, null, ASMHelper.getExceptionTypes(m)); mv.visitCode(); // load block instance mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, classname, "$$_provider", Type.getDescriptor(ComponentProvider.class)); mv.visitLdcInsn(clazzConst); // load component instance mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(ComponentProvider.class), "get", Type.getMethodDescriptor(Type.getType(Component.class), Type.getType(Class.class)), false); // add parameters Class<?>[] parameters = m.getParameterTypes(); for (int i = 0; i < m.getParameterCount(); i++) { mv.visitVarInsn(Type.getType(parameters[i]).getOpcode(ILOAD), i + 1); } // invoke mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(intf), m.getName(), descr, true); mv.visitInsn(isVoid ? RETURN : Type.getType(m.getReturnType()).getOpcode(IRETURN)); mv.visitMaxs(0, 0); mv.visitEnd(); } } clazzNode.visitEnd(); return ASMHelper.defineClass(clazzNode, ClassWriter.COMPUTE_MAXS, baseClazz.getProtectionDomain()); }