boolean (@NotNull IElementType tokenType, final PsiType ltype, final PsiType rtype, final boolean strict) { if (ltype == null || rtype == null) return true; int resultTypeRank = BOOL_RANK; boolean isApplicable = false; final int ltypeRank = getTypeRank(ltype); final int rtypeRank = getTypeRank(rtype); if (tokenType == JavaTokenType.LT || tokenType == JavaTokenType.LE || tokenType == JavaTokenType.GT || tokenType == JavaTokenType.GE) { if (isPrimitiveAndNotNullOrWrapper(ltype) && isPrimitiveAndNotNullOrWrapper(rtype)) { isApplicable = ltypeRank <= MAX_NUMERIC_RANK && rtypeRank <= MAX_NUMERIC_RANK; } } else if (tokenType == JavaTokenType.EQEQ || tokenType == JavaTokenType.NE) { if (isPrimitiveAndNotNullOrWrapper(ltype) && isPrimitiveAndNotNullOrWrapper(rtype) && (isPrimitiveAndNotNull(ltype) || isPrimitiveAndNotNull(rtype))) { isApplicable = ltypeRank <= MAX_NUMERIC_RANK && rtypeRank <= MAX_NUMERIC_RANK || ltypeRank == BOOL_RANK && rtypeRank == BOOL_RANK; } else { if (isPrimitiveAndNotNull(ltype)) { if (rtype instanceof PsiClassType) { final LanguageLevel languageLevel = ((PsiClassType)rtype).getLanguageLevel(); return languageLevel.isAtLeast(LanguageLevel.JDK_1_5) && !languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && areTypesConvertible(ltype, rtype); } return false; } if (isPrimitiveAndNotNull(rtype)) { if (ltype instanceof PsiClassType) { final LanguageLevel level = ((PsiClassType)ltype).getLanguageLevel(); return level.isAtLeast(LanguageLevel.JDK_1_7) && !level.isAtLeast(LanguageLevel.JDK_1_8) && areTypesConvertible(rtype, ltype); } return false; } isApplicable = areTypesConvertible(ltype, rtype) || areTypesConvertible(rtype, ltype); } } else if (tokenType == JavaTokenType.PLUS) { if (ltype.equalsToText(JAVA_LANG_STRING)) { isApplicable = !isVoidType(rtype); resultTypeRank = STRING_RANK; } else if (rtype.equalsToText(JAVA_LANG_STRING)) { if (isVoidType(ltype)) { return false; } return !strict || ltype.isAssignableFrom(rtype); } else if (isPrimitiveAndNotNullOrWrapper(ltype) && isPrimitiveAndNotNullOrWrapper(rtype)) { resultTypeRank = Math.max(ltypeRank, rtypeRank); isApplicable = ltypeRank <= MAX_NUMERIC_RANK && rtypeRank <= MAX_NUMERIC_RANK; } } else if (tokenType == JavaTokenType.ASTERISK || tokenType == JavaTokenType.DIV || tokenType == JavaTokenType.PERC || tokenType == JavaTokenType.MINUS) { if (isPrimitiveAndNotNullOrWrapper(ltype) && isPrimitiveAndNotNullOrWrapper(rtype)) { resultTypeRank = Math.max(ltypeRank, rtypeRank); isApplicable = ltypeRank <= MAX_NUMERIC_RANK && rtypeRank <= MAX_NUMERIC_RANK; } } else if (tokenType == JavaTokenType.LTLT || tokenType == JavaTokenType.GTGT || tokenType == JavaTokenType.GTGTGT) { if (isPrimitiveAndNotNullOrWrapper(ltype) && isPrimitiveAndNotNullOrWrapper(rtype)) { isApplicable = ltypeRank <= LONG_RANK && rtypeRank <= LONG_RANK; resultTypeRank = INT_RANK; } } else if (tokenType == JavaTokenType.AND || tokenType == JavaTokenType.OR || tokenType == JavaTokenType.XOR) { if (isPrimitiveAndNotNullOrWrapper(ltype) && isPrimitiveAndNotNullOrWrapper(rtype)) { isApplicable = ltypeRank <= LONG_RANK && rtypeRank <= LONG_RANK || isBooleanType(ltype) && isBooleanType(rtype); resultTypeRank = ltypeRank <= LONG_RANK ? INT_RANK : BOOL_RANK; } } else if (tokenType == JavaTokenType.ANDAND || tokenType == JavaTokenType.OROR) { if (isPrimitiveAndNotNullOrWrapper(ltype) && isPrimitiveAndNotNullOrWrapper(rtype)) { isApplicable = isBooleanType(ltype) && isBooleanType(rtype); } } if (isApplicable && strict && resultTypeRank > MAX_NUMERIC_RANK) { isApplicable = ltypeRank == resultTypeRank || ltype.equalsToText(JAVA_LANG_OBJECT); } return isApplicable; }