@@ -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