Nullability (@Nullable PsiExpression expression, boolean useDataflow) { expression = PsiUtil.skipParenthesizedExprDown(expression); if (expression == null) return Nullability.UNKNOWN; if (PsiTypes.nullType().equals(expression.getType())) return Nullability.NULLABLE; if (expression instanceof PsiNewExpression || expression instanceof PsiLiteralExpression || expression instanceof PsiPolyadicExpression || expression instanceof PsiFunctionalExpression || expression.getType() instanceof PsiPrimitiveType) { return Nullability.NOT_NULL; } if (expression instanceof PsiConditionalExpression) { PsiExpression thenExpression = ((PsiConditionalExpression)expression).getThenExpression(); PsiExpression elseExpression = ((PsiConditionalExpression)expression).getElseExpression(); if (thenExpression == null || elseExpression == null) return Nullability.UNKNOWN; PsiExpression condition = ((PsiConditionalExpression)expression).getCondition(); // simple cases like x == null ? something : x PsiReferenceExpression ref = ExpressionUtils.getReferenceExpressionFromNullComparison(condition, true); if (ref != null && JavaPsiEquivalenceUtil.areExpressionsEquivalent(ref, elseExpression)) { return getExpressionNullability(thenExpression, useDataflow); } // x != null ? x : something ref = ExpressionUtils.getReferenceExpressionFromNullComparison(condition, false); if (ref != null && JavaPsiEquivalenceUtil.areExpressionsEquivalent(ref, thenExpression)) { return getExpressionNullability(elseExpression, useDataflow); } if (useDataflow) { return DfaNullability.toNullability(DfaNullability.fromDfType(CommonDataflow.getDfType(expression))); } Nullability left = getExpressionNullability(thenExpression, false); if (left == Nullability.UNKNOWN) return Nullability.UNKNOWN; Nullability right = getExpressionNullability(elseExpression, false); return left == right ? left : Nullability.UNKNOWN; } if (expression instanceof PsiTypeCastExpression) { return getExpressionNullability(((PsiTypeCastExpression)expression).getOperand(), useDataflow); } if (expression instanceof PsiAssignmentExpression assignment) { if(assignment.getOperationTokenType().equals(JavaTokenType.EQ)) { return getExpressionNullability(assignment.getRExpression(), useDataflow); } return Nullability.NOT_NULL; } if (useDataflow) { return DfaNullability.toNullability(DfaNullability.fromDfType(CommonDataflow.getDfType(expression))); } if (expression instanceof PsiReferenceExpression ref) { PsiElement target = ref.resolve(); if (target instanceof PsiPatternVariable) { return Nullability.NOT_NULL; // currently all pattern variables are not-null } if (target instanceof PsiLocalVariable || target instanceof PsiParameter) { PsiElement block = PsiUtil.getVariableCodeBlock((PsiVariable)target, null); // Do not trust the declared nullability of local variable/parameter if it's reassigned as nullability designates // only initial nullability if (block == null || !HighlightControlFlowUtil.isEffectivelyFinal((PsiVariable)target, block, ref)) return Nullability.UNKNOWN; } return DfaPsiUtil.getElementNullabilityIgnoringParameterInference(expression.getType(), (PsiModifierListOwner)target); } if (expression instanceof PsiMethodCallExpression || expression instanceof PsiTemplateExpression) { PsiMethod method = ((PsiCall)expression).resolveMethod(); return method != null ? DfaPsiUtil.getElementNullability(expression.getType(), method) : Nullability.UNKNOWN; } return Nullability.UNKNOWN; }