@Override protected IMethod[] getDeclaredIMethods2() { List<IMethod> iMethods = new ArrayList(); for (ClassFile.MethodInfo mi : this.classFile.methodInfos) { // Skip JDK 1.5 synthetic methods (e.g. those generated for // covariant return values). if (Mod.isSynthetic(mi.getModifierFlags())) continue; IInvocable ii; try { ii = this.resolveMethod(mi); } catch (ClassNotFoundException ex) { throw new JaninoRuntimeException(ex.getMessage(), ex); } if (ii instanceof IMethod) iMethods.add((IMethod) ii); } return (IMethod[]) iMethods.toArray(new IMethod[iMethods.size()]); }
/** * 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; }