public static Exprent contractStringConcat(Exprent expr) {

    Exprent exprTmp = null;
    VarType cltype = null;

    // first quick test
    if (expr.type == Exprent.EXPRENT_INVOCATION) {
      InvocationExprent iex = (InvocationExprent)expr;
      if ("toString".equals(iex.getName())) {
        if (builderClass.equals(iex.getClassName())) {
          cltype = builderType;
        }
        else if (bufferClass.equals(iex.getClassName())) {
          cltype = bufferType;
        }
        if (cltype != null) {
          exprTmp = iex.getInstance();
        }
      }
      else if ("makeConcatWithConstants".equals(iex.getName())) { // java 9 style
        List<Exprent> parameters = extractParameters(iex.getBootstrapArguments(), iex);
        if (parameters.size() >= 2) {
          return createConcatExprent(parameters, expr.bytecode);
        }
      }
    }

    if (exprTmp == null) {
      return expr;
    }


    // iterate in depth, collecting possible operands
    List<Exprent> lstOperands = new ArrayList<>();

    while (true) {

      int found = 0;

      switch (exprTmp.type) {
        case Exprent.EXPRENT_INVOCATION -> {
          InvocationExprent iex = (InvocationExprent)exprTmp;
          if (isAppendConcat(iex, cltype)) {
            lstOperands.add(0, iex.getParameters().get(0));
            exprTmp = iex.getInstance();
            found = 1;
          }
        }
        case Exprent.EXPRENT_NEW -> {
          NewExprent nex = (NewExprent)exprTmp;
          if (isNewConcat(nex, cltype)) {
            VarType[] params = nex.getConstructor().getDescriptor().params;
            if (params.length == 1) {
              lstOperands.add(0, nex.getConstructor().getParameters().get(0));
            }
            found = 2;
          }
        }
      }

      if (found == 0) {
        return expr;
      }
      else if (found == 2) {
        break;
      }
    }

    int first2str = 0;
    int index = 0;
    while (index < lstOperands.size() && index < 2) {
      if (lstOperands.get(index).getExprType().equals(VarType.VARTYPE_STRING)) {
        first2str |= (index + 1);
      }
      index++;
    }

    if (first2str == 0) {
      lstOperands.add(0, new ConstExprent(VarType.VARTYPE_STRING, "", expr.bytecode));
    }

    // remove redundant String.valueOf
    for (int i = 0; i < lstOperands.size(); i++) {
      Exprent rep = removeStringValueOf(lstOperands.get(i));

      boolean ok = (i > 1);
      if (!ok) {
        boolean isstr = rep.getExprType().equals(VarType.VARTYPE_STRING);
        ok = isstr || first2str != i + 1;

        if (i == 0) {
          first2str &= 2;
        }
      }

      if (ok) {
        lstOperands.set(i, rep);
      }
    }
    return createConcatExprent(lstOperands, expr.bytecode);
  }
public static Exprent contractStringConcat(Exprent expr)