@Nullable
  private static PsiVariable findReplacement(@NotNull PsiMethod method,
                                             @NotNull PsiVariable castedVar,
                                             @NotNull PsiTypeCastExpression expression) {
    if (InstanceOfUtils.isUncheckedCast(expression)) return null;
    PsiTypeElement expressionCastType = expression.getCastType();
    if (expressionCastType == null) return null;
    final PsiCodeBlock methodBody = method.getBody();
    if (methodBody == null) return null;
    final TextRange expressionTextRange = expression.getTextRange();
    if (expressionTextRange == null) return null;
    PsiExpression operand = PsiUtil.skipParenthesizedExprDown(expression.getOperand());
    if (operand == null) return null;
    PsiType castType = expressionCastType.getType();
    List<PsiTypeCastExpression> found =
      SyntaxTraverser.psiTraverser(method)
        .filter(PsiTypeCastExpression.class)
        .filter(cast -> EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(cast.getOperand(), operand))
        .filter(cast -> {
          PsiTypeElement typeElement = cast.getCastType();
          return typeElement != null && InstanceOfUtils.typeCompatible(typeElement.getType(), castType, operand);
        })
        .toList();
    PsiResolveHelper resolveHelper = PsiResolveHelper.getInstance(method.getProject());
    for (PsiTypeCastExpression occurrence : found) {
      if (!isAtRightLocation(expression, expressionTextRange, occurrence)) continue;

      final PsiLocalVariable variable = getVariable(occurrence);

      if (variable != null &&
          resolveHelper.resolveReferencedVariable(variable.getName(), expression) == variable &&
          !isChangedBetween(castedVar, methodBody, occurrence, expression) &&
          !isChangedBetween(variable, methodBody, occurrence, expression)) {
        return variable;
      }
    }

    PsiInstanceOfExpression instanceOf = InstanceOfUtils.findPatternCandidate(expression);
    if (instanceOf != null) {
      PsiPattern pattern = instanceOf.getPattern();
      PsiPatternVariable patternVariable = JavaPsiPatternUtil.getPatternVariable(pattern);
      if (patternVariable != null &&
          !isChangedBetween(castedVar, methodBody, instanceOf, expression) &&
          !isChangedBetween(patternVariable, methodBody, instanceOf, expression)) {
        return patternVariable;
      }
    }

    List<PsiAssignmentExpression> narrowVariables =
      SyntaxTraverser.psiTraverser(method)
        .filter(PsiAssignmentExpression.class)
        .filter(assignment -> EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(assignment.getLExpression(), operand))
        .filter(assignment -> {
          PsiExpression narrowVariable = assignment.getRExpression();
          return narrowVariable != null && narrowVariable.getType() != null && InstanceOfUtils.typeCompatible(narrowVariable.getType(), castType, operand);
        })
        .toList();
    for (PsiAssignmentExpression narrowVariable : narrowVariables) {
      if (!isAtRightLocation(expression,  expressionTextRange, narrowVariable)) continue;

      final PsiLocalVariable declaration = getVariable(narrowVariable);

      if (declaration != null &&
          resolveHelper.resolveReferencedVariable(declaration.getName(), expression) == declaration &&
          !isChangedBetween(castedVar, methodBody, narrowVariable, expression) &&
          !isChangedBetween(declaration, methodBody, narrowVariable, expression)) {
        return declaration;
      }
    }

    if (!(operand instanceof PsiReferenceExpression wideReferenceExpression)
        || !(wideReferenceExpression.resolve() instanceof PsiLocalVariable wideVariable)) return null;

    PsiExpression narrowExpression = wideVariable.getInitializer();
    if (!(narrowExpression instanceof PsiReferenceExpression narrowReferenceExpression)
        || !(narrowReferenceExpression.resolve() instanceof PsiVariable narrowVariable)
        || narrowExpression.getType() == null
        || !InstanceOfUtils.typeCompatible(narrowExpression.getType(), castType, operand)) return null;

    if (!isAtRightLocation(expression, expressionTextRange, narrowExpression)) return null;

    if (narrowVariable.getName() == null
        || resolveHelper.resolveReferencedVariable(narrowVariable.getName(), expression) != narrowVariable
        || isChangedBetween(castedVar, methodBody, narrowExpression, expression)
        || isChangedBetween(narrowVariable, methodBody, narrowExpression, expression)) return null;

    return narrowVariable;
  }
@Nullable
  private static PsiVariable findReplacement(@NotNull PsiMethod method,
                                             @NotNull PsiVariable castedVar,
                                             @NotNull PsiTypeCastExpression expression)