public Object visitBinary()

in java/java.hints/src/org/netbeans/modules/java/hints/ArithmeticUtilities.java [525:876]


        public Object visitBinary(BinaryTree node, Void p) {
            Object left  = scan(node.getLeftOperand(), p);
            Object right = scan(node.getRightOperand(), p);
            
            // JSL 5.6.2, binary numeric promotion + JLS 5.1.2, widening primitive conversion for char values.
            // other value types are handled by the Number class in JDK. Chars may be promoted further to float / double.
            if (left instanceof Character && !(right instanceof String)) {
                left = Integer.valueOf(((Character)left).charValue());
            }
            if (right instanceof Character && !(left instanceof String)) {
                right = Integer.valueOf(((Character)right).charValue());
            }
            if (left != null && right != null) {
                Object result = null;
                switch (node.getKind()) {
                    case EQUAL_TO:
                        if (left instanceof Number && right instanceof Number) {
                            result = numericBinaryOp(OP_EQUAL, left, right);
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() == rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() == rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() == rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() == rn.intValue();
                            } else {
                                return null;
                            }
                        } else if (left instanceof Boolean && right instanceof Boolean) {
                            return left.equals(right);
                        } else if (left == NULL || right == NULL) {
                            // cannot accept primitives, boxing conversion does not apply
                            TypeMirror m = info.getTrees().getTypeMirror(
                                    new TreePath(getCurrentPath(), 
                                        left == NULL ?  node.getRightOperand() : 
                                                        node.getLeftOperand()
                            ));
                            if (Utilities.isValidType(m) && !PRIMITIVE_KINDS.contains(m.getKind())) {
                                result = left == right;
                            }
                        }
                        break;
                        
                    case NOT_EQUAL_TO:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() != rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() != rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() != rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() != rn.intValue();
                            } else {
                                return null;
                            }
                        } else if (left instanceof Boolean && right instanceof Boolean) {
                            return left.equals(right);
                        } else if (enhanceProcessing && (left == NULL || right == NULL)) {
                            // cannot accept primitives, boxing conversion does not apply
                            TypeMirror m = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), 
                                    left == NULL ? node.getRightOperand() : node.getLeftOperand()));
                            if (Utilities.isValidType(m) && !PRIMITIVE_KINDS.contains(m.getKind())) {
                                result = left != right;
                            }
                        }
                        break;
                        
                    case LESS_THAN:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() < rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() < rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() < rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() < rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;
                    case LESS_THAN_EQUAL:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() <= rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() <= rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() <= rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() <= rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;
                    case GREATER_THAN:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() > rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() > rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() > rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() > rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;
                    case GREATER_THAN_EQUAL:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() >= rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() >= rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() >= rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() >= rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;
                        
                    case MULTIPLY:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() * rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() * rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() * rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() * rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;

                    case DIVIDE:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() / rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() / rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() / rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() / rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        boolean a = true;
                        boolean b = false;
                        boolean c = a & b;
                        break;
                        
                    case REMAINDER:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() % rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() % rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() % rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() % rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;

                    case MINUS:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() - rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() - rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() - rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() - rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;

                    case LEFT_SHIFT:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() << rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() << rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;

                    case RIGHT_SHIFT:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() >> rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() >> rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;

                    case UNSIGNED_RIGHT_SHIFT:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() >>> rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() >>> rn.intValue();
                            } else {
                                return null;
                            }
                        }
                        break;

                    // PLUS is also supported for String operands. `null' value is represented by String containing "null",
                    // so it will produce the correct concatenation result.
                    case PLUS:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Double || right instanceof Double) {
                                result = ln.doubleValue() + rn.doubleValue();
                            } else if (left instanceof Float || right instanceof Float) {
                                result = ln.floatValue() + rn.floatValue();
                            } else if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() + rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() + rn.intValue();
                            } else {
                                return null;
                            }
                        } else if (left instanceof String) {
                            if (right != NOT_NULL) {
                                result = (String)left + right;
                            }
                        } else if (right instanceof String) {
                            if (left != NOT_NULL) {
                                result = left + (String)right;
                            }
                        }
                        break;

                    // AND, OR apply as well to booleans
                    case CONDITIONAL_AND:
                        if (left instanceof Boolean && right instanceof Boolean) {
                            result = ((Boolean)left) && ((Boolean)right);
                        }
                        break;
                    case CONDITIONAL_OR:
                        if (left instanceof Boolean && right instanceof Boolean) {
                            result = ((Boolean)left) || ((Boolean)right);
                        }
                        break;
                    case XOR:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() ^ rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() ^ rn.intValue();
                            } else {
                                return null;
                            }
                        } else if (left instanceof Boolean && right instanceof Boolean) {
                            result = ((Boolean)left) ^ ((Boolean)right);
                        }
                        break;

                    case AND:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() & rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() & rn.intValue();
                            } else {
                                return null;
                            }
                        } else if (left instanceof Boolean && right instanceof Boolean) {
                            result = ((Boolean)left) & ((Boolean)right);
                        }
                        break;

                    case OR:
                        if (left instanceof Number && right instanceof Number) {
                            Number ln = (Number)left;
                            Number rn = (Number)right;
                            if (left instanceof Long || right instanceof Long) {
                                result = ln.longValue() | rn.longValue();
                            } else if (integerLike(ln) || integerLike(rn)) {
                                result = ln.intValue() | rn.intValue();
                            } else {
                                return null;
                            }
                        } else if (left instanceof Boolean && right instanceof Boolean) {
                            result = ((Boolean)left) | ((Boolean)right);
                        }
                        break;
                }

                return result;
            }

            return null;
        }