Example #1
0
 @Override
 public void visit(InvokeInstruction insn) {
   Expr[] exprArgs = new Expr[insn.getMethod().getParameterTypes().length];
   for (int i = 0; i < insn.getArguments().size(); ++i) {
     exprArgs[i] = Expr.var(insn.getArguments().get(i).getIndex());
   }
   InvocationExpr invocationExpr;
   if (insn.getInstance() != null) {
     if (insn.getType() == InvocationType.VIRTUAL) {
       invocationExpr =
           Expr.invoke(insn.getMethod(), Expr.var(insn.getInstance().getIndex()), exprArgs);
     } else {
       invocationExpr =
           Expr.invokeSpecial(insn.getMethod(), Expr.var(insn.getInstance().getIndex()), exprArgs);
     }
   } else {
     invocationExpr = Expr.invokeStatic(insn.getMethod(), exprArgs);
   }
   AssignmentStatement stmt;
   if (insn.getReceiver() != null) {
     stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), invocationExpr);
     stmt.getDebugNames().addAll(insn.getReceiver().getDebugNames());
   } else {
     stmt = Statement.assign(null, invocationExpr);
   }
   stmt.setLocation(currentLocation);
   stmt.setAsync(async);
   async = false;
   statements.add(stmt);
 }
 private List<Instruction> transformSetterInvocation(InvokeInstruction insn, String property) {
   ValueType type = insn.getMethod().getDescriptor().parameterType(0);
   List<Instruction> instructions = new ArrayList<>();
   if (type instanceof ValueType.Primitive) {
     switch (((ValueType.Primitive) type).getKind()) {
       case BOOLEAN:
         castAndSetProperty(insn, property, instructions, boolean.class);
         return instructions;
       case BYTE:
         castAndSetProperty(insn, property, instructions, byte.class);
         return instructions;
       case SHORT:
         castAndSetProperty(insn, property, instructions, short.class);
         return instructions;
       case INTEGER:
         castAndSetProperty(insn, property, instructions, int.class);
         return instructions;
       case FLOAT:
         castAndSetProperty(insn, property, instructions, float.class);
         return instructions;
       case DOUBLE:
         castAndSetProperty(insn, property, instructions, double.class);
         return instructions;
       case CHARACTER:
       case LONG:
         break;
     }
   } else if (type instanceof ValueType.Object) {
     switch (((ValueType.Object) type).getClassName()) {
       case "java.lang.String":
         {
           Variable castVar = insn.getProgram().createVariable();
           InvokeInstruction castInvoke = new InvokeInstruction();
           castInvoke.setType(InvocationType.SPECIAL);
           castInvoke.setMethod(
               new MethodReference(
                   ResourceAccessor.class, "castFromString", String.class, Object.class));
           castInvoke.getArguments().add(insn.getArguments().get(0));
           castInvoke.setReceiver(castVar);
           instructions.add(castInvoke);
           setProperty(insn, property, instructions, castVar);
           return instructions;
         }
       default:
         {
           setProperty(insn, property, instructions, insn.getArguments().get(0));
           return instructions;
         }
     }
   }
   return null;
 }
 private void castAndSetProperty(
     InvokeInstruction insn, String property, List<Instruction> instructions, Class<?> primitive) {
   Variable castVar = program.createVariable();
   InvokeInstruction castInvoke = new InvokeInstruction();
   castInvoke.setType(InvocationType.SPECIAL);
   String primitiveCapitalized = primitive.getName();
   primitiveCapitalized =
       Character.toUpperCase(primitiveCapitalized.charAt(0)) + primitiveCapitalized.substring(1);
   castInvoke.setMethod(
       new MethodReference(
           ResourceAccessor.class, "castFrom" + primitiveCapitalized, primitive, Object.class));
   castInvoke.getArguments().add(insn.getArguments().get(0));
   castInvoke.setReceiver(castVar);
   instructions.add(castInvoke);
   setProperty(insn, property, instructions, castVar);
 }
 private List<Instruction> transformInvoke(InvokeInstruction insn) {
   if (insn.getType() != InvocationType.VIRTUAL) {
     return null;
   }
   MethodReference method = insn.getMethod();
   if (method.getClassName().equals(ResourceArray.class.getName())
       || method.getClassName().equals(ResourceMap.class.getName())) {
     if (method.getName().equals("keys")) {
       return transformKeys(insn);
     }
     InvokeInstruction accessInsn = new InvokeInstruction();
     accessInsn.setType(InvocationType.SPECIAL);
     ValueType[] types = new ValueType[method.getDescriptor().parameterCount() + 2];
     types[0] = ValueType.object("java.lang.Object");
     System.arraycopy(
         method.getDescriptor().getSignature(),
         0,
         types,
         1,
         method.getDescriptor().parameterCount() + 1);
     accessInsn.setMethod(
         new MethodReference(ResourceAccessor.class.getName(), method.getName(), types));
     accessInsn.getArguments().add(insn.getInstance());
     accessInsn.getArguments().addAll(insn.getArguments());
     accessInsn.setReceiver(insn.getReceiver());
     return Arrays.asList(accessInsn);
   }
   ClassReader iface = innerSource.get(method.getClassName());
   if (iface == null
       || !innerSource.isSuperType(Resource.class.getName(), iface.getName()).orElse(false)) {
     return null;
   }
   if (method.getName().startsWith("get")) {
     if (method.getName().length() > 3) {
       return transformGetterInvocation(insn, getPropertyName(method.getName().substring(3)));
     }
   } else if (method.getName().startsWith("is")) {
     if (method.getName().length() > 2) {
       return transformGetterInvocation(insn, getPropertyName(method.getName().substring(2)));
     }
   } else if (method.getName().startsWith("set")) {
     if (method.getName().length() > 3) {
       return transformSetterInvocation(insn, getPropertyName(method.getName().substring(3)));
     }
   }
   return null;
 }
 private void setProperty(
     InvokeInstruction insn, String property, List<Instruction> instructions, Variable valueVar) {
   Variable nameVar = program.createVariable();
   StringConstantInstruction nameInsn = new StringConstantInstruction();
   nameInsn.setConstant(property);
   nameInsn.setReceiver(nameVar);
   instructions.add(nameInsn);
   InvokeInstruction accessorInvoke = new InvokeInstruction();
   accessorInvoke.setType(InvocationType.SPECIAL);
   accessorInvoke.setMethod(
       new MethodReference(
           ResourceAccessor.class, "put", Object.class, String.class, Object.class, void.class));
   accessorInvoke.getArguments().add(insn.getInstance());
   accessorInvoke.getArguments().add(nameVar);
   accessorInvoke.getArguments().add(valueVar);
   instructions.add(accessorInvoke);
 }
 @Override
 public void visit(InvokeInstruction insn) {
   if (insn.getInstance() != null) {
     escaping[insn.getInstance().getIndex()] = true;
   }
   for (Variable arg : insn.getArguments()) {
     escaping[arg.getIndex()] = true;
   }
 }
  private List<Instruction> transformKeys(InvokeInstruction insn) {
    Variable tmp = program.createVariable();

    InvokeInstruction keysInsn = new InvokeInstruction();
    keysInsn.setType(InvocationType.SPECIAL);
    keysInsn.setMethod(
        new MethodReference(ResourceAccessor.class, "keys", Object.class, Object.class));
    keysInsn.getArguments().add(insn.getInstance());
    keysInsn.setReceiver(tmp);

    InvokeInstruction transformInsn = new InvokeInstruction();
    transformInsn.setType(InvocationType.SPECIAL);
    transformInsn.setMethod(
        new MethodReference(ResourceAccessor.class, "keysToStrings", Object.class, String[].class));
    transformInsn.getArguments().add(tmp);
    transformInsn.setReceiver(insn.getReceiver());

    return Arrays.asList(keysInsn, transformInsn);
  }