private static boolean replaceInvocations(
      Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {

    boolean res = false;

    while (true) {

      boolean found = false;

      for (Exprent expr : exprent.getAllExprents()) {
        String cl = isClass14Invocation(expr, wrapper, meth);
        if (cl != null) {
          exprent.replaceExprent(
              expr, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/'), expr.bytecode));
          found = true;
          res = true;
          break;
        }

        res |= replaceInvocations(expr, wrapper, meth);
      }

      if (!found) {
        break;
      }
    }

    return res;
  }
示例#2
0
  public void classLambdaToJava(
      ClassNode node,
      TextBuffer buffer,
      Exprent method_object,
      int indent,
      BytecodeMappingTracer origTracer) {
    ClassWrapper wrapper = node.getWrapper();
    if (wrapper == null) {
      return;
    }

    boolean lambdaToAnonymous =
        DecompilerContext.getOption(IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS);

    ClassNode outerNode =
        (ClassNode) DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
    DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);

    BytecodeMappingTracer tracer = new BytecodeMappingTracer(origTracer.getCurrentSourceLine());

    try {
      StructClass cl = wrapper.getClassStruct();

      DecompilerContext.getLogger().startWriteClass(node.simpleName);

      if (node.lambdaInformation.is_method_reference) {
        if (!node.lambdaInformation.is_content_method_static && method_object != null) {
          // reference to a virtual method
          buffer.append(method_object.toJava(indent, tracer));
        } else {
          // reference to a static method
          buffer.append(
              ExprProcessor.getCastTypeName(
                  new VarType(node.lambdaInformation.content_class_name, false)));
        }

        buffer.append("::");
        buffer.append(node.lambdaInformation.content_method_name);
      } else {
        // lambda method
        StructMethod mt = cl.getMethod(node.lambdaInformation.content_method_key);
        MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
        MethodDescriptor md_content =
            MethodDescriptor.parseDescriptor(node.lambdaInformation.content_method_descriptor);
        MethodDescriptor md_lambda =
            MethodDescriptor.parseDescriptor(node.lambdaInformation.method_descriptor);

        if (!lambdaToAnonymous) {
          buffer.append('(');

          boolean firstParameter = true;
          int index = node.lambdaInformation.is_content_method_static ? 0 : 1;
          int start_index = md_content.params.length - md_lambda.params.length;

          for (int i = 0; i < md_content.params.length; i++) {
            if (i >= start_index) {
              if (!firstParameter) {
                buffer.append(", ");
              }

              String parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0));
              buffer.append(
                  parameterName == null
                      ? "param" + index
                      : parameterName); // null iff decompiled with errors

              firstParameter = false;
            }

            index += md_content.params[i].stackSize;
          }

          buffer.append(") ->");
        }

        buffer.append(" {").appendLineSeparator();
        tracer.incrementCurrentSourceLine();

        methodLambdaToJava(node, wrapper, mt, buffer, indent + 1, !lambdaToAnonymous, tracer);

        buffer.appendIndent(indent).append("}");

        addTracer(cl, mt, tracer);
      }
    } finally {
      DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, outerNode);
    }

    DecompilerContext.getLogger().endWriteClass();
  }
示例#3
0
  private void fieldToJava(
      ClassWrapper wrapper,
      StructClass cl,
      StructField fd,
      TextBuffer buffer,
      int indent,
      BytecodeMappingTracer tracer) {
    int start = buffer.length();
    boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
    boolean isDeprecated = fd.getAttributes().containsKey("Deprecated");
    boolean isEnum =
        fd.hasModifier(CodeConstants.ACC_ENUM)
            && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);

    if (isDeprecated) {
      appendDeprecation(buffer, indent);
    }

    if (interceptor != null) {
      String oldName =
          interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor());
      appendRenameComment(buffer, oldName, MType.FIELD, indent);
    }

    if (fd.isSynthetic()) {
      appendComment(buffer, "synthetic field", indent);
    }

    appendAnnotations(buffer, fd, indent);

    buffer.appendIndent(indent);

    if (!isEnum) {
      appendModifiers(buffer, fd.getAccessFlags(), FIELD_ALLOWED, isInterface, FIELD_EXCLUDED);
    }

    VarType fieldType = new VarType(fd.getDescriptor(), false);

    GenericFieldDescriptor descriptor = null;
    if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
      StructGenericSignatureAttribute attr =
          (StructGenericSignatureAttribute) fd.getAttributes().getWithKey("Signature");
      if (attr != null) {
        descriptor = GenericMain.parseFieldSignature(attr.getSignature());
      }
    }

    if (!isEnum) {
      if (descriptor != null) {
        buffer.append(GenericMain.getGenericCastTypeName(descriptor.type));
      } else {
        buffer.append(ExprProcessor.getCastTypeName(fieldType));
      }
      buffer.append(' ');
    }

    buffer.append(fd.getName());

    tracer.incrementCurrentSourceLine(buffer.countLines(start));

    Exprent initializer;
    if (fd.hasModifier(CodeConstants.ACC_STATIC)) {
      initializer =
          wrapper
              .getStaticFieldInitializers()
              .getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()));
    } else {
      initializer =
          wrapper
              .getDynamicFieldInitializers()
              .getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()));
    }
    if (initializer != null) {
      if (isEnum && initializer.type == Exprent.EXPRENT_NEW) {
        NewExprent nexpr = (NewExprent) initializer;
        nexpr.setEnumConst(true);
        buffer.append(nexpr.toJava(indent, tracer));
      } else {
        buffer.append(" = ");
        // FIXME: special case field initializer. Can map to more than one method (constructor) and
        // bytecode intruction.
        buffer.append(initializer.toJava(indent, tracer));
      }
    } else if (fd.hasModifier(CodeConstants.ACC_FINAL)
        && fd.hasModifier(CodeConstants.ACC_STATIC)) {
      StructConstantValueAttribute attr =
          (StructConstantValueAttribute)
              fd.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_CONSTANT_VALUE);
      if (attr != null) {
        PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex());
        buffer.append(" = ");
        buffer.append(new ConstExprent(fieldType, constant.value, null).toJava(indent, tracer));
      }
    }

    if (!isEnum) {
      buffer.append(";").appendLineSeparator();
      tracer.incrementCurrentSourceLine();
    }
  }