String (@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation, Collection<MemberInfo> memberInfos) { final boolean callSuper = readCallSuperAnnotationOrConfigProperty(psiAnnotation, psiClass, ConfigKey.EQUALSANDHASHCODE_CALL_SUPER); final boolean doNotUseGetters = readAnnotationOrConfigProperty(psiAnnotation, psiClass, "doNotUseGetters", ConfigKey.EQUALSANDHASHCODE_DO_NOT_USE_GETTERS); final StringBuilder builder = new StringBuilder(); if (!memberInfos.isEmpty()) { builder.append("final int PRIME = ").append(PRIME_FOR_HASHCODE).append(";\n"); } builder.append("int result = "); if (callSuper) { builder.append("super.hashCode();\n"); } else { builder.append("1;\n"); } for (MemberInfo memberInfo : memberInfos) { final String memberAccessor = EqualsAndHashCodeToStringHandler.getMemberAccessorName(memberInfo, doNotUseGetters, psiClass); final String memberName = memberInfo.getMethod() == null ? memberInfo.getName() : "$" + memberInfo.getName(); final PsiType classFieldType = memberInfo.getType(); if (classFieldType instanceof PsiPrimitiveType) { if (PsiTypes.booleanType().equals(classFieldType)) { builder.append("result = result * PRIME + (this.").append(memberAccessor).append(" ? ").append(PRIME_FOR_TRUE).append(" : ") .append(PRIME_FOR_FALSE).append(");\n"); } else if (PsiTypes.longType().equals(classFieldType)) { builder.append("final long $").append(memberName).append(" = this.").append(memberAccessor).append(";\n"); builder.append("result = result * PRIME + (int)($").append(memberName).append(" >>> 32 ^ $").append(memberName).append(");\n"); } else if (PsiTypes.floatType().equals(classFieldType)) { builder.append("result = result * PRIME + java.lang.Float.floatToIntBits(this.").append(memberAccessor).append(");\n"); } else if (PsiTypes.doubleType().equals(classFieldType)) { builder.append("final long $").append(memberName).append(" = java.lang.Double.doubleToLongBits(this.").append(memberAccessor) .append(");\n"); builder.append("result = result * PRIME + (int)($").append(memberName).append(" >>> 32 ^ $").append(memberName).append(");\n"); } else { builder.append("result = result * PRIME + this.").append(memberAccessor).append(";\n"); } } else if (classFieldType instanceof PsiArrayType) { final PsiType componentType = ((PsiArrayType)classFieldType).getComponentType(); if (componentType instanceof PsiPrimitiveType) { builder.append("result = result * PRIME + java.util.Arrays.hashCode(this.").append(memberAccessor).append(");\n"); } else { builder.append("result = result * PRIME + java.util.Arrays.deepHashCode(this.").append(memberAccessor).append(");\n"); } } else { builder.append("final java.lang.Object $").append(memberName).append(" = this.").append(memberAccessor).append(";\n"); builder.append("result = result * PRIME + ($").append(memberName).append(" == null ? " + PRIME_FOR_NULL + " : $").append(memberName) .append(".hashCode());\n"); } } builder.append("return result;\n"); return builder.toString(); }