508 /** Diagnose a modifier flag from the set, if any. */ |
509 /** Diagnose a modifier flag from the set, if any. */ |
509 protected void checkNoMods(long mods) { |
510 protected void checkNoMods(long mods) { |
510 if (mods != 0) { |
511 if (mods != 0) { |
511 long lowestMod = mods & -mods; |
512 long lowestMod = mods & -mods; |
512 error(token.pos, "mod.not.allowed.here", |
513 error(token.pos, "mod.not.allowed.here", |
513 Flags.asFlagSet(lowestMod)); |
514 Flags.asFlagSet(lowestMod)); |
514 } |
515 } |
515 } |
516 } |
516 |
517 |
517 /* ---------- doc comments --------- */ |
518 /* ---------- doc comments --------- */ |
518 |
519 |
971 } |
969 } |
972 } |
970 } |
973 /** If tree is a concatenation of string literals, replace it |
971 /** If tree is a concatenation of string literals, replace it |
974 * by a single literal representing the concatenated string. |
972 * by a single literal representing the concatenated string. |
975 */ |
973 */ |
976 protected StringBuilder foldStrings(JCTree tree) { |
974 protected JCExpression foldStrings(JCExpression tree) { |
977 if (!allowStringFolding) |
975 if (!allowStringFolding) |
978 return null; |
976 return null; |
979 List<String> buf = List.nil(); |
977 ListBuffer<JCExpression> opStack = new ListBuffer<>(); |
|
978 ListBuffer<JCLiteral> litBuf = new ListBuffer<>(); |
|
979 boolean needsFolding = false; |
|
980 JCExpression curr = tree; |
980 while (true) { |
981 while (true) { |
981 if (tree.hasTag(LITERAL)) { |
982 if (curr.hasTag(JCTree.Tag.PLUS)) { |
982 JCLiteral lit = (JCLiteral) tree; |
983 JCBinary op = (JCBinary)curr; |
983 if (lit.typetag == TypeTag.CLASS) { |
984 needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false); |
984 StringBuilder sbuf = |
985 curr = op.lhs; |
985 new StringBuilder((String)lit.value); |
986 } else { |
986 while (buf.nonEmpty()) { |
987 needsFolding |= foldIfNeeded(curr, litBuf, opStack, true); |
987 sbuf.append(buf.head); |
988 break; //last one! |
988 buf = buf.tail; |
|
989 } |
|
990 return sbuf; |
|
991 } |
|
992 } else if (tree.hasTag(JCTree.Tag.PLUS)) { |
|
993 JCBinary op = (JCBinary)tree; |
|
994 if (op.rhs.hasTag(LITERAL)) { |
|
995 JCLiteral lit = (JCLiteral) op.rhs; |
|
996 if (lit.typetag == TypeTag.CLASS) { |
|
997 buf = buf.prepend((String) lit.value); |
|
998 tree = op.lhs; |
|
999 continue; |
|
1000 } |
|
1001 } |
|
1002 } |
989 } |
1003 return null; |
990 } |
1004 } |
991 if (needsFolding) { |
1005 } |
992 List<JCExpression> ops = opStack.toList(); |
|
993 JCExpression res = ops.head; |
|
994 for (JCExpression op : ops.tail) { |
|
995 res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op); |
|
996 storeEnd(res, getEndPos(op)); |
|
997 } |
|
998 return res; |
|
999 } else { |
|
1000 return tree; |
|
1001 } |
|
1002 } |
|
1003 |
|
1004 private boolean foldIfNeeded(JCExpression tree, ListBuffer<JCLiteral> litBuf, |
|
1005 ListBuffer<JCExpression> opStack, boolean last) { |
|
1006 JCLiteral str = stringLiteral(tree); |
|
1007 if (str != null) { |
|
1008 litBuf.prepend(str); |
|
1009 return last && merge(litBuf, opStack); |
|
1010 } else { |
|
1011 boolean res = merge(litBuf, opStack); |
|
1012 litBuf.clear(); |
|
1013 opStack.prepend(tree); |
|
1014 return res; |
|
1015 } |
|
1016 } |
|
1017 |
|
1018 boolean merge(ListBuffer<JCLiteral> litBuf, ListBuffer<JCExpression> opStack) { |
|
1019 if (litBuf.isEmpty()) { |
|
1020 return false; |
|
1021 } else if (litBuf.size() == 1) { |
|
1022 opStack.prepend(litBuf.first()); |
|
1023 return false; |
|
1024 } else { |
|
1025 JCExpression t = F.at(litBuf.first().getStartPosition()).Literal(TypeTag.CLASS, |
|
1026 litBuf.stream().map(lit -> (String)lit.getValue()).collect(Collectors.joining())); |
|
1027 storeEnd(t, litBuf.last().getEndPosition(endPosTable)); |
|
1028 opStack.prepend(t); |
|
1029 return true; |
|
1030 } |
|
1031 } |
|
1032 |
|
1033 private JCLiteral stringLiteral(JCTree tree) { |
|
1034 if (tree.hasTag(LITERAL)) { |
|
1035 JCLiteral lit = (JCLiteral)tree; |
|
1036 if (lit.typetag == TypeTag.CLASS) { |
|
1037 return lit; |
|
1038 } |
|
1039 } |
|
1040 return null; |
|
1041 } |
|
1042 |
1006 |
1043 |
1007 /** optimization: To save allocating a new operand/operator stack |
1044 /** optimization: To save allocating a new operand/operator stack |
1008 * for every binary operation, we use supplys. |
1045 * for every binary operation, we use supplys. |
1009 */ |
1046 */ |
1010 ArrayList<JCExpression[]> odStackSupply = new ArrayList<>(); |
1047 ArrayList<JCExpression[]> odStackSupply = new ArrayList<>(); |