code: protected JCExpression foldStrings(JCExpression tree) {
              if (!allowStringFolding)
                  return tree;
              ListBuffer<JCExpression> opStack = new ListBuffer<>();
              ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
              boolean needsFolding = false;
              JCExpression curr = tree;
              while (true) {
                  if (curr.hasTag(JCTree.Tag.PLUS)) {
                      JCBinary op = (JCBinary)curr;
                      needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
                      curr = op.lhs;
                  } else {
                      needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
                      break; //last one!
                  }
              }
              if (needsFolding) {
                  List<JCExpression> ops = opStack.toList();
                  JCExpression res = ops.head;
                  for (JCExpression op : ops.tail) {
                      res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op);
                      storeEnd(res, getEndPos(op));
                  }
                  return res;
              } else {
                  return tree;
              }
          }
docs: If tree is a concatenation of string literals, replace it
  by a single literal representing the concatenated string.