예제 #1
0
  /**
   * 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;
  }
예제 #2
0
  /** @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)));
  }