public static void processNonArrayExpression(ClassInstanceReferenceVisitor visitor, PsiExpression expression, PsiElement referencedElement) {
    expression = CommonJavaRefactoringUtil.outermostParenthesizedExpression(expression);
    PsiElement parent = expression.getParent();
    if(parent instanceof PsiReferenceExpression && expression == ((PsiReferenceExpression) parent).getQualifierExpression()) {
      visitor.visitQualifier((PsiReferenceExpression) parent, expression, referencedElement);
    }
    else if (parent instanceof PsiTypeCastExpression) {
      visitor.visitTypeCast((PsiTypeCastExpression)parent, expression, referencedElement);
    }
    else if (parent instanceof PsiReturnStatement returnStatement) {
      PsiType returnType =
        PsiTreeUtil.getParentOfType(returnStatement, PsiMethod.class, PsiLambdaExpression.class) instanceof PsiMethod method
        ? method.getReturnType()
        : null;
      visitor.visitReadUsage(expression, returnType, referencedElement);
    }
    else if (parent instanceof PsiStatement) {
      visitor.visitReadUsage(expression, null, referencedElement);
    }
    else if (parent instanceof PsiExpressionList expressionList) {
      PsiElement pparent = expressionList.getParent();
      if (pparent instanceof PsiStatement) {
        visitor.visitReadUsage(expression, null, referencedElement);
      }
      else if (pparent instanceof PsiCallExpression callExpression) {
        PsiExpression[] arguments = callExpression.getArgumentList().getExpressions();
        PsiMethod method = callExpression.resolveMethod();
        if (method != null) {
          int index = ArrayUtil.indexOf(arguments, expression);
          if (index >= 0) {
            PsiParameter[] parameters = method.getParameterList().getParameters();
            if (parameters.length > index) {
              visitor.visitReadUsage(expression, parameters[index].getType(), referencedElement);
            }
          }
        }
      }
    }
    else if (parent instanceof PsiAssignmentExpression assignmentExpression) {
      if (expression.equals(assignmentExpression.getRExpression())) {
        visitor.visitReadUsage(expression, assignmentExpression.getLExpression().getType(), referencedElement);
      }
      else { // LExpression
        visitor.visitWriteUsage(expression, assignmentExpression.getRExpression().getType(), referencedElement);
      }
    }
    else if (RefactoringUtil.isAssignmentLHS(expression)) {
      visitor.visitWriteUsage(expression, null, referencedElement);
    }
    else if(parent instanceof PsiVariable) {
      visitor.visitReadUsage(expression, ((PsiVariable) parent).getType(), referencedElement);
    }
    else if(parent instanceof PsiExpression) {
      // for usages in expressions other than above, we do not care about the type
      visitor.visitReadUsage(expression, null, referencedElement);
    }
    else {
      LOG.error("Unknown variation of class instance usage");
    }
  }
public static void processNonArrayExpression(ClassInstanceReferenceVisitor visitor, PsiExpression expression, PsiElement referencedElement)