/** * Turn a {@link ClassFile.MethodInfo} into an {@link IInvocable}. This includes the checking and * the removal of the magic first parameter of an inner class constructor. * * @param methodInfo * @throws ClassNotFoundException */ private IInvocable resolveMethod(final ClassFile.MethodInfo methodInfo) throws ClassNotFoundException { IInvocable result = (IInvocable) this.resolvedMethods.get(methodInfo); if (result != null) return result; // Determine method name. final String name = methodInfo.getName(); // Determine return type. MethodDescriptor md = new MethodDescriptor(methodInfo.getDescriptor()); final IClass returnType = this.resolveClass(md.returnFd); // Determine parameter types. final IClass[] parameterTypes = new IClass[md.parameterFds.length]; for (int i = 0; i < parameterTypes.length; ++i) parameterTypes[i] = this.resolveClass(md.parameterFds[i]); // Determine thrown exceptions. IClass[] tes = null; ClassFile.AttributeInfo[] ais = methodInfo.getAttributes(); for (ClassFile.AttributeInfo ai : ais) { if (ai instanceof ClassFile.ExceptionsAttribute) { ConstantClassInfo[] ccis = ((ClassFile.ExceptionsAttribute) ai).getExceptions(this.classFile); tes = new IClass[ccis.length]; for (int i = 0; i < tes.length; ++i) { tes[i] = this.resolveClass(Descriptor.fromInternalForm(ccis[i].getName(this.classFile))); } } } final IClass[] thrownExceptions = tes == null ? new IClass[0] : tes; // Determine access. final Access access = ClassFileIClass.accessFlags2Access(methodInfo.getModifierFlags()); if ("<init>".equals(name)) { result = new IClass.IConstructor() { @Override public boolean isVarargs() { return Mod.isVarargs(methodInfo.getModifierFlags()); } @Override public IClass[] getParameterTypes2() throws CompileException { // Process magic first parameter of inner class constructor. IClass outerIClass = ClassFileIClass.this.getOuterIClass(); if (outerIClass != null) { if (parameterTypes.length < 1) { throw new JaninoRuntimeException( "Inner class constructor lacks magic first parameter"); } if (parameterTypes[0] != outerIClass) { throw new JaninoRuntimeException( "Magic first parameter of inner class constructor has type \"" + parameterTypes[0].toString() + "\" instead of that of its enclosing instance (\"" + outerIClass.toString() + "\")"); } IClass[] tmp = new IClass[parameterTypes.length - 1]; System.arraycopy(parameterTypes, 1, tmp, 0, tmp.length); return tmp; } return parameterTypes; } @Override public IClass[] getThrownExceptions2() { return thrownExceptions; } @Override public Access getAccess() { return access; } @Override public Java.Annotation[] getAnnotations() { return methodInfo.getAnnotations(); } }; } else { result = new IClass.IMethod() { @Override public String getName() { return name; } @Override public IClass getReturnType() { return returnType; } @Override public boolean isStatic() { return Mod.isStatic(methodInfo.getModifierFlags()); } @Override public boolean isAbstract() { return Mod.isAbstract(methodInfo.getModifierFlags()); } @Override public boolean isVarargs() { return Mod.isVarargs(methodInfo.getModifierFlags()); } @Override public IClass[] getParameterTypes2() { return parameterTypes; } @Override public IClass[] getThrownExceptions2() { return thrownExceptions; } @Override public Access getAccess() { return access; } @Override public Java.Annotation[] getAnnotations() { return methodInfo.getAnnotations(); } }; } this.resolvedMethods.put(methodInfo, result); return result; }
/** @param index Index of the CONSTANT_Class_info to resolve (JVMS 4.4.1) */ private IClass resolveClass(short index) throws ClassNotFoundException { ClassFileIClass.LOGGER.entering(null, "resolveClass", index); ConstantClassInfo cci = (ConstantClassInfo) this.classFile.getConstantPoolInfo(index); return this.resolveClass(Descriptor.fromInternalForm(cci.getName(this.classFile))); }