IDEA-141475 (serialVersionUID generated by IDEA differs from one generated by JDK)

This commit is contained in:
Bas Leijdekkers
2015-06-17 21:51:16 +02:00
parent b7ba21fe54
commit 910433e916
5 changed files with 83 additions and 89 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Bas Leijdekkers
* Copyright 2003-2015 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,8 +25,6 @@ public class MemberSignature implements Comparable<MemberSignature> {
@NonNls private static final String INITIALIZER_SIGNATURE = "()V";
@NonNls private static final MemberSignature ASSERTIONS_DISABLED_FIELD =
new MemberSignature("$assertionsDisabled", Modifier.STATIC | Modifier.FINAL, "Z");
@NonNls private static final MemberSignature CLASS_ACCESS_METHOD =
new MemberSignature("class$", Modifier.STATIC, "(Ljava.lang.String;)Ljava.lang.Class;");
@NonNls private static final MemberSignature PACKAGE_PRIVATE_CONSTRUCTOR =
new MemberSignature(CONSTRUCTOR_NAME, 0, INITIALIZER_SIGNATURE);
@NonNls private static final MemberSignature PUBLIC_CONSTRUCTOR =
@@ -235,11 +233,6 @@ public class MemberSignature implements Comparable<MemberSignature> {
return ASSERTIONS_DISABLED_FIELD;
}
public static MemberSignature getClassAccessMethodMemberSignature() {
return CLASS_ACCESS_METHOD;
}
public int getModifiers() {
return modifiers;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2012 Bas Leijdekkers
* Copyright 2003-2015 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,9 +45,7 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
private final Set<MemberSignature> nonPrivateFields;
private final List<MemberSignature> staticInitializers;
private boolean assertStatement = false;
private boolean classObjectAccessExpression = false;
private final Map<PsiElement, String> memberMap =
new HashMap<PsiElement, String>();
private final Map<PsiElement, String> memberMap = new HashMap<PsiElement, String>();
private static final Comparator<PsiClass> INTERFACE_COMPARATOR =
new Comparator<PsiClass>() {
@@ -76,7 +74,6 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
return name1.compareTo(name2);
}
};
@NonNls private static final String CLASS_ACCESS_METHOD_PREFIX = "class$";
private SerialVersionUIDBuilder(PsiClass clazz) {
super();
@@ -103,7 +100,7 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
}
}
staticInitializers = new ArrayList<MemberSignature>();
staticInitializers = new ArrayList<MemberSignature>(1);
final PsiClassInitializer[] initializers = clazz.getInitializers();
if (initializers.length > 0) {
for (final PsiClassInitializer initializer : initializers) {
@@ -130,8 +127,8 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
}
}
nonPrivateConstructors = new HashSet<MemberSignature>();
final PsiMethod[] constructors = clazz.getConstructors();
nonPrivateConstructors = new HashSet<MemberSignature>(constructors.length);
if (constructors.length == 0 && !clazz.isInterface()) {
// generated empty constructor if no constructor is defined in the source
final MemberSignature constructorSignature;
@@ -152,6 +149,9 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
}
}
/**
* @see java.io.ObjectStreamClass#computeDefaultSUID(java.lang.Class)
*/
public static long computeDefaultSUID(PsiClass psiClass) {
final Project project = psiClass.getProject();
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
@@ -197,34 +197,15 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
}
final MemberSignature[] fields = serialVersionUIDBuilder.getNonPrivateFields();
Arrays.sort(fields);
for (final MemberSignature field : fields) {
dataOutputStream.writeUTF(field.getName());
dataOutputStream.writeInt(field.getModifiers());
dataOutputStream.writeUTF(field.getSignature());
}
writeSignatures(fields, dataOutputStream);
final MemberSignature[] staticInitializers = serialVersionUIDBuilder.getStaticInitializers();
for (final MemberSignature staticInitializer : staticInitializers) {
dataOutputStream.writeUTF(staticInitializer.getName());
dataOutputStream.writeInt(staticInitializer.getModifiers());
dataOutputStream.writeUTF(staticInitializer.getSignature());
}
writeSignatures(staticInitializers, dataOutputStream);
final MemberSignature[] constructors = serialVersionUIDBuilder.getNonPrivateConstructors();
Arrays.sort(constructors);
for (final MemberSignature constructor : constructors) {
dataOutputStream.writeUTF(constructor.getName());
dataOutputStream.writeInt(constructor.getModifiers());
dataOutputStream.writeUTF(constructor.getSignature());
}
writeSignatures(constructors, dataOutputStream);
Arrays.sort(methodSignatures);
for (final MemberSignature methodSignature : methodSignatures) {
dataOutputStream.writeUTF(methodSignature.getName());
dataOutputStream.writeInt(methodSignature.getModifiers());
dataOutputStream.writeUTF(methodSignature.getSignature());
}
writeSignatures(methodSignatures, dataOutputStream);
dataOutputStream.flush();
@NonNls final String algorithm = "SHA";
@@ -248,43 +229,13 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
}
}
private void createClassObjectAccessSynthetics(PsiType type) {
if (!classObjectAccessExpression) {
final MemberSignature syntheticMethod =
MemberSignature.getClassAccessMethodMemberSignature();
nonPrivateMethods.add(syntheticMethod);
private static void writeSignatures(MemberSignature[] signatures, DataOutputStream dataOutputStream) throws IOException {
Arrays.sort(signatures);
for (final MemberSignature field : signatures) {
dataOutputStream.writeUTF(field.getName());
dataOutputStream.writeInt(field.getModifiers());
dataOutputStream.writeUTF(field.getSignature());
}
PsiType unwrappedType = type;
@NonNls final StringBuffer fieldNameBuffer;
if (type instanceof PsiArrayType) {
fieldNameBuffer = new StringBuffer();
fieldNameBuffer.append("array");
while (unwrappedType instanceof PsiArrayType) {
final PsiArrayType arrayType = (PsiArrayType)unwrappedType;
unwrappedType = arrayType.getComponentType();
fieldNameBuffer.append('$');
}
}
else {
fieldNameBuffer = new StringBuffer(CLASS_ACCESS_METHOD_PREFIX);
}
if (unwrappedType instanceof PsiPrimitiveType) {
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)unwrappedType;
fieldNameBuffer.append(MemberSignature.createPrimitiveType(primitiveType));
}
else {
final String text = unwrappedType.getCanonicalText().replace('.',
'$');
fieldNameBuffer.append(text);
}
final String fieldName = fieldNameBuffer.toString();
final MemberSignature memberSignature =
new MemberSignature(fieldName, Modifier.STATIC,
"Ljava/lang/Class;");
if (!nonPrivateFields.contains(memberSignature)) {
nonPrivateFields.add(memberSignature);
}
classObjectAccessExpression = true;
}
private String getAccessMethodIndex(PsiElement element) {
@@ -351,10 +302,6 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
final MemberSignature memberSignature =
MemberSignature.getAssertionsDisabledFieldMemberSignature();
nonPrivateFields.add(memberSignature);
final PsiManager manager = clazz.getManager();
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiClassType classType = factory.createType(clazz);
createClassObjectAccessSynthetics(classType);
if (staticInitializers.isEmpty()) {
final MemberSignature initializerSignature =
MemberSignature.getStaticInitializerMemberSignature();
@@ -363,17 +310,6 @@ public class SerialVersionUIDBuilder extends JavaRecursiveElementVisitor {
assertStatement = true;
}
@Override
public void visitClassObjectAccessExpression(
PsiClassObjectAccessExpression expression) {
final PsiTypeElement operand = expression.getOperand();
final PsiType type = operand.getType();
if (!(type instanceof PsiPrimitiveType)) {
createClassObjectAccessSynthetics(type);
}
super.visitClassObjectAccessExpression(expression);
}
@Override
public void visitMethodCallExpression(
@NotNull PsiMethodCallExpression methodCallExpression) {
@@ -0,0 +1,15 @@
import java.io.Serializable;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
public class ClassAccess implements Serializable {
private static final long serialVersionUID = 2269507042140353173L;
enum TestEnum {}
Map<TestEnum, Set<String>> testField = new EnumMap<TestEnum, Set<String>>(TestEnum.class);
// Map<TestEnum, Set<String>> testField = new HashMap<>();
}
@@ -0,0 +1,14 @@
import java.io.Serializable;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
public class ClassAccess<caret> implements Serializable {
enum TestEnum {}
// at one point javac generated a synthetic field for .class accesses with a name starting with the string "class$"
Map<TestEnum, Set<String>> testField = new EnumMap<TestEnum, Set<String>>(TestEnum.class);
// Map<TestEnum, Set<String>> testField = new HashMap<>();
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.fixes.serialization;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.IGQuickFixesTestCase;
import com.siyeh.ig.serialization.SerializableHasSerialVersionUIDFieldInspection;
/**
* @author Bas Leijdekkers
*/
public class AddSerialVersionUIDFixTest extends IGQuickFixesTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(new SerializableHasSerialVersionUIDFieldInspection());
myRelativePath = "serialization/serialVersionUID";
myDefaultHint = InspectionGadgetsBundle.message("add.serialversionuidfield.quickfix");
}
public void testClassAccess() { doTest(); }
}