@Override
  public int hashCode(PsiExpression e) {
    if (e == null) {
      return 0;
    }
    if (e instanceof PsiParenthesizedExpression) {
      return hashCode(((PsiParenthesizedExpression)e).getExpression());
    }
    if (e instanceof PsiUnaryExpression unary) {
      return hashCode(unary.getOperationTokenType(), unary.getOperand());
    }
    if (e instanceof PsiPolyadicExpression polyadic) {
      return hashCode(polyadic.getOperationTokenType(), polyadic.getOperands());
    }
    if (e instanceof PsiConditionalExpression conditional) {
      return hashCode(JavaTokenType.QUEST, conditional.getCondition(),
                             conditional.getThenExpression(), conditional.getElseExpression());
    }
    if (e instanceof PsiMethodCallExpression call) {
      PsiReferenceExpression ref = call.getMethodExpression();
      String name = ref.getReferenceName();
      PsiExpression qualifier = ref.getQualifierExpression();
      PsiExpression[] args = call.getArgumentList().getExpressions();
      if (qualifier != null) {
        if ("get".equals(name) && (qualifier.textMatches("Paths") || qualifier.textMatches("java.nio.file.Paths")) ||
            "of".equals(name) && qualifier.textMatches("java.nio.file.Path")) {
          return hashCode("of", "Path", args); 
        }
      }
      return hashCode(name, qualifier, args);
    }
    if (e instanceof PsiReferenceExpression ref) {
      return hashCode(ref.getReferenceName(), ref.getQualifierExpression());
    }
    if (e instanceof PsiInstanceOfExpression instanceOf) {
      return hashCode(getTypeName(instanceOf.getCheckType()), instanceOf.getOperand());
    }
    if (e instanceof PsiArrayAccessExpression access) {
      return hashCode(JavaTokenType.LBRACKET, access.getArrayExpression(), access.getIndexExpression());
    }
    if (e instanceof PsiClassObjectAccessExpression) {
      String name = getTypeName(((PsiClassObjectAccessExpression)e).getOperand());
      return name != null ? name.hashCode() : 0;
    }
    if (e instanceof PsiLambdaExpression) {
      PsiExpression bodyExpr = LambdaUtil.extractSingleExpressionFromBody(((PsiLambdaExpression)e).getBody());
      return hashCode(JavaTokenType.ARROW, bodyExpr) * 31 + ((PsiLambdaExpression)e).getParameterList().getParametersCount();
    }
    if (e instanceof PsiLiteralExpression) {
      Object value = ((PsiLiteralExpression)e).getValue();
      return value != null ? value.hashCode() : 0;
    }
    return 0;
  }
@Override
  public int hashCode(PsiExpression e)