PsiType (final PsiExpression expr) { if (expr == null) return null; final LinkedList<PsiType> e = myTypeMap.get(new TypeMigrationUsageInfo(expr)); if (e != null) { return e.getFirst(); } if (expr instanceof PsiArrayAccessExpression arrayAccess) { if (evaluateType(arrayAccess.getArrayExpression()) instanceof PsiArrayType arrayType) { return arrayType.getComponentType(); } } else if (expr instanceof PsiAssignmentExpression assignment) { return evaluateType(assignment.getLExpression()); } else if (expr instanceof PsiMethodCallExpression call) { final JavaResolveResult resolveResult = call.resolveMethodGenerics(); final PsiMethod method = (PsiMethod)resolveResult.getElement(); if (method != null) { final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiExpression[] actualParms = call.getArgumentList().getExpressions(); return PsiUtil.captureToplevelWildcards(createMethodSubstitution(parameters, actualParms, method, call, resolveResult.getSubstitutor(), false).substitute(evaluateType(call.getMethodExpression())), expr); } } else if (expr instanceof PsiPolyadicExpression polyadic) { final PsiExpression[] operands = polyadic.getOperands(); final IElementType sign = polyadic.getOperationTokenType(); PsiType lType = operands.length > 0 ? evaluateType(operands[0]) : null; for (int i = 1; i < operands.length; i++) { lType = TypeConversionUtil.calcTypeForBinaryExpression(lType, evaluateType(operands[i]), sign, true); } return lType; } else if (expr instanceof PsiUnaryExpression unary) { return evaluateType(unary.getOperand()); } else if (expr instanceof PsiParenthesizedExpression paren) { return evaluateType(paren.getExpression()); } else if (expr instanceof PsiConditionalExpression conditional) { final PsiExpression thenExpression = conditional.getThenExpression(); final PsiExpression elseExpression = conditional.getElseExpression(); final PsiType thenType = evaluateType(thenExpression); final PsiType elseType = evaluateType(elseExpression); return switch ((thenType == null ? 0 : 1) + (elseType == null ? 0 : 2)) { case 0 -> expr.getType(); case 1 -> thenType; case 2 -> elseType; case 3 -> { if (TypeConversionUtil.areTypesConvertible(thenType, elseType)) { yield thenType; } else if (TypeConversionUtil.areTypesConvertible(elseType, thenType)) { yield elseType; } else { yield switch ((thenType.equals(thenExpression.getType()) ? 0 : 1) + (elseType.equals(elseExpression.getType()) ? 0 : 2)) { case 0, 3 -> expr.getType(); case 1 -> thenType; case 2 -> elseType; default -> throw new AssertionError(); }; } } default -> throw new AssertionError(); }; } else if (expr instanceof PsiNewExpression newExpression) { final PsiExpression qualifier = newExpression.getQualifier(); if (qualifier != null) { final PsiClassType.ClassResolveResult qualifierResult = resolveType(evaluateType(qualifier)); if (qualifierResult.getElement() != null) { final PsiSubstitutor qualifierSubs = qualifierResult.getSubstitutor(); final PsiClassType.ClassResolveResult result = resolveType(expr.getType()); if (result.getElement() != null) { final PsiClass aClass = result.getElement(); return JavaPsiFacade.getElementFactory(aClass.getProject()) .createType(aClass, result.getSubstitutor().putAll(qualifierSubs)); } } } } else if (expr instanceof PsiFunctionalExpression functionalExpression) { final PsiType functionalInterfaceType = functionalExpression.getFunctionalInterfaceType(); if (functionalInterfaceType != null) { return functionalInterfaceType; } } else if (expr instanceof PsiReferenceExpression) { final PsiType type = evaluateReferenceExpressionType(expr); if (type != null) { return PsiImplUtil.normalizeWildcardTypeByPosition(type, expr); } } else if (expr instanceof PsiSuperExpression) { final PsiClass psiClass = PsiTreeUtil.getParentOfType(expr, PsiClass.class); if (psiClass != null) { final PsiClass superClass = psiClass.getSuperClass(); if (superClass != null) { return getType(new TypeMigrationUsageInfo(superClass)); } } } return getType(expr); }