Skip to content

Commit 1475faa

Browse files
committed
fixing String + double/float/Double/Float
1 parent 5fc0bc8 commit 1475faa

File tree

3 files changed

+188
-136
lines changed

3 files changed

+188
-136
lines changed

sources/net.sf.j2s.core/src/net/sf/j2s/core/astvisitors/ASTKeywordVisitor.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,16 +1474,22 @@ public boolean visit(VariableDeclarationStatement node) {
14741474
public boolean visit(WhileStatement node) {
14751475
buffer.append("while (");
14761476
node.getExpression().accept(this);
1477-
buffer.append(") ");
14781477
node.getBody().accept(this);
14791478
buffer.append("\r\n");
14801479
return false;
14811480
}
14821481

1483-
protected void boxingNode(ASTNode element) {
1482+
/**
1483+
* box or unbox as necessary
1484+
*
1485+
* @param element
1486+
* @return true if boxing or unboxing
1487+
*/
1488+
protected boolean boxingNode(ASTNode element) {
14841489
if (element instanceof Expression) {
14851490
Expression exp = (Expression) element;
14861491
if (exp.resolveBoxing()) {
1492+
// expression is the site of a boxing conversion
14871493
ITypeBinding typeBinding = exp.resolveTypeBinding();
14881494
if (typeBinding.isPrimitive()) {
14891495
String name = typeBinding.getName();
@@ -1493,9 +1499,10 @@ protected void boxingNode(ASTNode element) {
14931499
getBuffer().append("new " + name + " (");
14941500
element.accept(this);
14951501
getBuffer().append(")");
1496-
return;
1502+
return true;
14971503
}
14981504
} else if (exp.resolveUnboxing()) {
1505+
// expression is the site of an unboxing conversion
14991506
ITypeBinding typeBinding = exp.resolveTypeBinding();
15001507
if (!typeBinding.isPrimitive()) {
15011508
String name = typeBinding.getQualifiedName();
@@ -1504,11 +1511,12 @@ protected void boxingNode(ASTNode element) {
15041511
getBuffer().append("(");
15051512
element.accept(this);
15061513
getBuffer().append(")." + name + "Value ()");
1507-
return;
1514+
return true;
15081515
}
15091516
}
15101517
}
15111518
element.accept(this);
1519+
return false;
15121520
}
15131521

15141522
private final static String defaultNonQualified =

sources/net.sf.j2s.core/src/net/sf/j2s/core/astvisitors/ASTScriptVisitor.java

Lines changed: 164 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -949,178 +949,218 @@ private boolean checkInfixOperator(InfixExpression node) {
949949
return false;
950950
}
951951

952-
private void charVisit(ASTNode node, boolean beCare) {
953-
if (!beCare || !(node instanceof Expression)) {
954-
boxingNode(node);
955-
return;
956-
}
957-
Expression exp = (Expression) node;
958-
ITypeBinding binding = exp.resolveTypeBinding();
959-
if (binding.isPrimitive() && "char".equals(binding.getName())) {
960-
if (node instanceof CharacterLiteral) {
961-
CharacterLiteral cl = (CharacterLiteral) node;
962-
buffer.append(0 + cl.charValue());
963-
} else if (node instanceof SimpleName || node instanceof QualifiedName) {
964-
boxingNode(node);
965-
buffer.append(".charCodeAt (0)");
966-
} else {
967-
int idx1 = buffer.length();
968-
if (node instanceof PrefixExpression || node instanceof PostfixExpression
969-
|| node instanceof ParenthesizedExpression) {
970-
boxingNode(node);
971-
} else {
972-
buffer.append("(");
973-
boxingNode(node);
974-
buffer.append(")");
975-
}
976-
977-
boolean appendingCode = true;
978-
int length = buffer.length();
979-
if (exp instanceof MethodInvocation) {
980-
MethodInvocation m = (MethodInvocation) exp;
981-
if ("charAt".equals(m.getName().toString())) {
982-
int idx2 = buffer.indexOf(".charAt ", idx1);
983-
if (idx2 != -1) {
984-
StringBuffer newMethodBuffer = new StringBuffer();
985-
newMethodBuffer.append(buffer.substring(idx1 + 1, idx2));
986-
newMethodBuffer.append(".charCodeAt ");
987-
newMethodBuffer.append(buffer.substring(idx2 + 8, length - 1));
988-
buffer.delete(idx1, length);
989-
buffer.append(newMethodBuffer.toString());
990-
appendingCode = false;
991-
}
992-
}
993-
}
994-
if (appendingCode) {
995-
buffer.append(".charCodeAt (0)");
996-
}
997-
}
998-
} else {
999-
boxingNode(node);
1000-
}
1001-
}
1002-
1003952
public boolean visit(InfixExpression node) {
953+
// TODO check for String + Double/Float --> String + ... .toString()
954+
// and change to String + double/float --> String + new
955+
// Double/Float(...).toString()
1004956
String constValue = checkConstantValue(node);
1005957
if (constValue != null) {
1006958
buffer.append(constValue);
1007959
return false;
1008960
}
1009961
ITypeBinding expTypeBinding = node.resolveTypeBinding();
1010-
boolean beCare = false;
1011-
if (expTypeBinding != null && expTypeBinding.getName().indexOf("String") == -1) {
1012-
beCare = true;
1013-
}
962+
if (expTypeBinding == null)
963+
return false;
964+
boolean toString = (expTypeBinding.getName().indexOf("String") >= 0);
1014965
String operator = node.getOperator().toString();
1015966
Expression left = node.getLeftOperand();
1016967
Expression right = node.getRightOperand();
1017-
ITypeBinding typeBinding = left.resolveTypeBinding();
1018-
1019-
if (/*
1020-
* (left instanceof SimpleName || left instanceof CharacterLiteral)
1021-
* && (right instanceof SimpleName || right instanceof
1022-
* CharacterLiteral) &&
1023-
*/(">".equals(operator) || "<".equals(operator) || ">=".equals(operator) || "<=".equals(operator)
1024-
|| "==".equals(operator) || "!=".equals(operator))) {
1025-
ITypeBinding rightBinding = right.resolveTypeBinding();
1026-
if (typeBinding.isPrimitive() && "char".equals(typeBinding.getName()) && rightBinding.isPrimitive()
1027-
&& "char".equals(rightBinding.getName())) {
968+
ITypeBinding leftTypeBinding = left.resolveTypeBinding();
969+
ITypeBinding rightTypeBinding = right.resolveTypeBinding();
970+
if (leftTypeBinding == null || rightTypeBinding == null)
971+
return false;
972+
973+
if ("!==<=>=".indexOf(operator) >= 0) {
974+
// < > <= >= == !=
975+
if (leftTypeBinding.isPrimitive() && "char".equals(leftTypeBinding.getName())
976+
&& rightTypeBinding.isPrimitive() && "char".equals(rightTypeBinding.getName())) {
1028977
boxingNode(left);
1029978
buffer.append(' ');
1030979
buffer.append(operator);
1031980
buffer.append(' ');
1032981
boxingNode(right);
1033982
return false;
1034983
}
1035-
}
1036-
if ("/".equals(operator)) {
1037-
if (typeBinding != null && typeBinding.isPrimitive()) {
1038-
if (isIntegerType(typeBinding.getName())) {
1039-
ITypeBinding rightTypeBinding = right.resolveTypeBinding();
1040-
if (isIntegerType(rightTypeBinding.getName())) {
1041-
StringBuffer oldBuffer = buffer;
1042-
buffer = new StringBuffer();
1043-
buffer.append("Clazz.doubleToInt (");
1044-
charVisit(left, beCare);
984+
} else if ("/".equals(operator)) {
985+
if (leftTypeBinding.isPrimitive() && isIntegerType(leftTypeBinding.getName())
986+
&& isIntegerType(rightTypeBinding.getName())) {
987+
StringBuffer oldBuffer = buffer;
988+
buffer = new StringBuffer();
989+
buffer.append("Clazz.doubleToInt (");
990+
addOperand(left, toString, leftTypeBinding);
991+
buffer.append(' ');
992+
buffer.append(operator);
993+
buffer.append(' ');
994+
addOperand(right, toString, rightTypeBinding);
995+
buffer.append(')');
996+
List<?> extendedOperands = node.extendedOperands();
997+
if (extendedOperands.size() > 0) {
998+
for (Iterator<?> iter = extendedOperands.iterator(); iter.hasNext();) {
999+
ASTNode element = (ASTNode) iter.next();
1000+
boolean is2Floor = false;
1001+
if (element instanceof Expression) {
1002+
Expression exp = (Expression) element;
1003+
ITypeBinding expBinding = exp.resolveTypeBinding();
1004+
if (isIntegerType(expBinding.getName())) {
1005+
buffer.insert(0, "Clazz.doubleToInt (");
1006+
is2Floor = true;
1007+
}
1008+
}
10451009
buffer.append(' ');
10461010
buffer.append(operator);
10471011
buffer.append(' ');
1048-
charVisit(right, beCare);
1049-
buffer.append(')');
1050-
List<?> extendedOperands = node.extendedOperands();
1051-
if (extendedOperands.size() > 0) {
1052-
for (Iterator<?> iter = extendedOperands.iterator(); iter.hasNext();) {
1053-
ASTNode element = (ASTNode) iter.next();
1054-
boolean is2Floor = false;
1055-
if (element instanceof Expression) {
1056-
Expression exp = (Expression) element;
1057-
ITypeBinding expBinding = exp.resolveTypeBinding();
1058-
if (isIntegerType(expBinding.getName())) {
1059-
// buffer.insert(0, "Math.floor (");
1060-
buffer.insert(0, "Clazz.doubleToInt (");
1061-
is2Floor = true;
1062-
}
1063-
}
1064-
buffer.append(' ');
1065-
buffer.append(operator);
1066-
buffer.append(' ');
1067-
charVisit(element, beCare);
1068-
if (is2Floor) {
1069-
buffer.append(')');
1070-
}
1071-
}
1012+
addOperand(element, toString, ((Expression) element).resolveTypeBinding());
1013+
if (is2Floor) {
1014+
buffer.append(')');
10721015
}
1073-
1074-
oldBuffer.append(buffer);
1075-
buffer = oldBuffer;
1076-
oldBuffer = null;
1077-
1078-
return false;
10791016
}
10801017
}
1018+
oldBuffer.append(buffer);
1019+
buffer = oldBuffer;
1020+
oldBuffer = null;
1021+
return false;
10811022
}
10821023
}
1083-
boolean simple = false;
1084-
if (typeBinding != null && typeBinding.isPrimitive()) {
1085-
if ("boolean".equals(typeBinding.getName())) {
1024+
boolean toBoolean = false;
1025+
if (leftTypeBinding.isPrimitive()) {
1026+
if ("boolean".equals(leftTypeBinding.getName())) {
10861027
if (checkInfixOperator(node)) {
10871028
buffer.append(" new Boolean (");
1088-
simple = true;
1029+
toBoolean = true;
10891030
}
10901031
}
10911032
}
1092-
1093-
charVisit(left, beCare);
1033+
// left
1034+
addOperand(left, toString, leftTypeBinding);
10941035
buffer.append(' ');
1036+
// op
10951037
buffer.append(operator);
1096-
if ("==".equals(operator) || "!=".equals(operator)) {
1097-
if (typeBinding != null && !typeBinding.isPrimitive() && !(left instanceof NullLiteral)
1098-
&& !(right instanceof NullLiteral)
1099-
/*
1100-
* && !(node.getLeftOperand() instanceof StringLiteral) // "abc" ==
1101-
* ... && !(node.getRightOperand() instanceof StringLiteral)
1102-
*/) {
1103-
buffer.append('=');
1104-
}
1038+
if (("==".equals(operator) || "!=".equals(operator)) && !leftTypeBinding.isPrimitive()
1039+
&& !(left instanceof NullLiteral) && !(right instanceof NullLiteral)) {
1040+
buffer.append('=');
11051041
}
11061042
buffer.append(' ');
1107-
charVisit(right, beCare);
1043+
// right
1044+
addOperand(right, toString, rightTypeBinding);
1045+
1046+
// ok, this is trouble
1047+
// The extended operands is the preferred way of representing deeply
1048+
// nested expressions of the form L op R op R2 op R3... where the same
1049+
// operator appears between all the operands (the most common case being
1050+
// lengthy string concatenation expressions). Using the extended
1051+
// operands keeps the trees from getting too deep; this decreases the
1052+
// risk is running out of thread stack space at runtime when traversing
1053+
// such trees. ((a + b) + c) + d would be translated to: leftOperand: a
1054+
// rightOperand: b extendedOperands: {c, d} operator: +
1055+
11081056
List<?> extendedOperands = node.extendedOperands();
11091057
if (extendedOperands.size() > 0) {
11101058
for (Iterator<?> iter = extendedOperands.iterator(); iter.hasNext();) {
11111059
buffer.append(' ');
11121060
buffer.append(operator);
11131061
buffer.append(' ');
11141062
ASTNode element = (ASTNode) iter.next();
1115-
charVisit(element, beCare);
1063+
addOperand(element, toString, ((Expression) element).resolveTypeBinding());
11161064
}
11171065
}
1118-
if (simple) {
1066+
if (toBoolean) {
11191067
buffer.append(").valueOf ()");
11201068
}
11211069
return false;
11221070
}
11231071

1072+
/**
1073+
* add the operand, checking to see if it needs some adjustment:
1074+
*
1075+
* (a) String + x where x is {double/float} requires boxing Double/Float(x).toString()
1076+
*
1077+
* (b) String + x where x is {Double/Float} requires added .toString()
1078+
*
1079+
* (c)
1080+
*
1081+
* @param node
1082+
* @param toString
1083+
* @param typeBinding
1084+
*/
1085+
private void addOperand(ASTNode node, boolean toString, ITypeBinding typeBinding) {
1086+
if (!(node instanceof Expression)) {
1087+
// BH I don't see how node cannot be an expression
1088+
node.accept(this);
1089+
return;
1090+
}
1091+
if (toString) {
1092+
// BH
1093+
String prefix = null, suffix = null;
1094+
switch (typeBinding.getName()) {
1095+
case "double":
1096+
prefix = "new Double(";
1097+
suffix = ")";
1098+
break;
1099+
case "float":
1100+
prefix = "new Float(";
1101+
suffix = ")";
1102+
break;
1103+
case "Double":
1104+
case "Float":
1105+
prefix = suffix = "";
1106+
break;
1107+
default:
1108+
node.accept(this);
1109+
break;
1110+
}
1111+
if (prefix != null) {
1112+
buffer.append(prefix);
1113+
node.accept(this);
1114+
buffer.append(suffix);
1115+
buffer.append(".toString()");
1116+
}
1117+
return;
1118+
}
1119+
ITypeBinding binding = ((Expression) node).resolveTypeBinding();
1120+
if (!binding.isPrimitive() || !"char".equals(binding.getName())) {
1121+
boxingNode(node);
1122+
return;
1123+
}
1124+
// to char
1125+
if (node instanceof CharacterLiteral) {
1126+
CharacterLiteral cl = (CharacterLiteral) node;
1127+
buffer.append(0 + cl.charValue());
1128+
} else if (node instanceof SimpleName || node instanceof QualifiedName) {
1129+
boxingNode(node);
1130+
buffer.append(".charCodeAt (0)");
1131+
} else {
1132+
int idx1 = buffer.length();
1133+
if (node instanceof PrefixExpression || node instanceof PostfixExpression
1134+
|| node instanceof ParenthesizedExpression) {
1135+
boxingNode(node);
1136+
} else {
1137+
buffer.append("(");
1138+
boxingNode(node);
1139+
buffer.append(")");
1140+
}
1141+
boolean addCharCodeAt0 = true;
1142+
int length = buffer.length();
1143+
if (node instanceof MethodInvocation) {
1144+
MethodInvocation m = (MethodInvocation) node;
1145+
if ("charAt".equals(m.getName().toString())) {
1146+
int idx2 = buffer.indexOf(".charAt ", idx1);
1147+
if (idx2 != -1) {
1148+
StringBuffer newMethodBuffer = new StringBuffer();
1149+
newMethodBuffer.append(buffer.substring(idx1 + 1, idx2));
1150+
newMethodBuffer.append(".charCodeAt ");
1151+
newMethodBuffer.append(buffer.substring(idx2 + 8, length - 1));
1152+
buffer.delete(idx1, length);
1153+
buffer.append(newMethodBuffer.toString());
1154+
addCharCodeAt0 = false;
1155+
}
1156+
}
1157+
}
1158+
if (addCharCodeAt0) {
1159+
buffer.append(".charCodeAt (0)");
1160+
}
1161+
}
1162+
}
1163+
11241164
public boolean visit(Initializer node) {
11251165
if (checkj2sIgnore(node)) {
11261166
return false;

0 commit comments

Comments
 (0)