private static Evaluator createBinaryEvaluator(Evaluator lResult,
                                                   PsiType lType,
                                                   Evaluator rResult,
                                                   @NotNull PsiType rType,
                                                   @NotNull IElementType operation,
                                                   @NotNull PsiType expressionExpectedType) {
      // handle unboxing if necessary
      if (isUnboxingInBinaryExpressionApplicable(lType, rType, operation)) {
        if (rType instanceof PsiClassType && UnBoxingEvaluator.isTypeUnboxable(rType.getCanonicalText())) {
          rResult = new UnBoxingEvaluator(rResult);
        }
        if (lType instanceof PsiClassType && UnBoxingEvaluator.isTypeUnboxable(lType.getCanonicalText())) {
          lResult = new UnBoxingEvaluator(lResult);
        }
      }
      if (isBinaryNumericPromotionApplicable(lType, rType, operation)) {
        PsiType _lType = lType;
        final PsiPrimitiveType unboxedLType = PsiPrimitiveType.getUnboxedType(lType);
        if (unboxedLType != null) {
          _lType = unboxedLType;
        }

        PsiType _rType = rType;
        final PsiPrimitiveType unboxedRType = PsiPrimitiveType.getUnboxedType(rType);
        if (unboxedRType != null) {
          _rType = unboxedRType;
        }

        // handle numeric promotion
        if (PsiTypes.doubleType().equals(_lType)) {
          if (TypeConversionUtil.areTypesConvertible(_rType, PsiTypes.doubleType())) {
            rResult = createTypeCastEvaluator(rResult, PsiTypes.doubleType());
          }
        }
        else if (PsiTypes.doubleType().equals(_rType)) {
          if (TypeConversionUtil.areTypesConvertible(_lType, PsiTypes.doubleType())) {
            lResult = createTypeCastEvaluator(lResult, PsiTypes.doubleType());
          }
        }
        else if (PsiTypes.floatType().equals(_lType)) {
          if (TypeConversionUtil.areTypesConvertible(_rType, PsiTypes.floatType())) {
            rResult = createTypeCastEvaluator(rResult, PsiTypes.floatType());
          }
        }
        else if (PsiTypes.floatType().equals(_rType)) {
          if (TypeConversionUtil.areTypesConvertible(_lType, PsiTypes.floatType())) {
            lResult = createTypeCastEvaluator(lResult, PsiTypes.floatType());
          }
        }
        else if (PsiTypes.longType().equals(_lType)) {
          if (TypeConversionUtil.areTypesConvertible(_rType, PsiTypes.longType())) {
            rResult = createTypeCastEvaluator(rResult, PsiTypes.longType());
          }
        }
        else if (PsiTypes.longType().equals(_rType)) {
          if (TypeConversionUtil.areTypesConvertible(_lType, PsiTypes.longType())) {
            lResult = createTypeCastEvaluator(lResult, PsiTypes.longType());
          }
        }
        else {
          if (!PsiTypes.intType().equals(_lType) && TypeConversionUtil.areTypesConvertible(_lType, PsiTypes.intType())) {
            lResult = createTypeCastEvaluator(lResult, PsiTypes.intType());
          }
          if (!PsiTypes.intType().equals(_rType) && TypeConversionUtil.areTypesConvertible(_rType, PsiTypes.intType())) {
            rResult = createTypeCastEvaluator(rResult, PsiTypes.intType());
          }
        }
      }
      // unary numeric promotion if applicable
      else if (ExpressionParser.SHIFT_OPS.contains(operation)) {
        lResult = handleUnaryNumericPromotion(lType, lResult);
        rResult = handleUnaryNumericPromotion(rType, rResult);
      }

      return DisableGC.create(new BinaryExpressionEvaluator(lResult, rResult, operation, expressionExpectedType.getCanonicalText()));
    }
private static Evaluator createBinaryEvaluator(Evaluator lResult,
                                                   PsiType lType,
                                                   Evaluator rResult,
                                                   @NotNull PsiType rType,
                                                   @NotNull IElementType operation,
                                                   @NotNull PsiType expressionExpectedType)