diff options
Diffstat (limited to 'src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java')
-rw-r--r-- | src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java | 141 |
1 files changed, 71 insertions, 70 deletions
diff --git a/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 209c095c..847ea7d1 100644 --- a/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -81,7 +81,7 @@ import lombok.core.AnnotationValues; import lombok.core.AST.Kind; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; -import lombok.eclipse.EclipseAST.Node; +import lombok.eclipse.EclipseNode; /** * Handles the <code>EqualsAndHashCode</code> annotation for eclipse. @@ -91,23 +91,23 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA private static final Set<String> BUILT_IN_TYPES = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( "byte", "short", "int", "long", "char", "boolean", "double", "float"))); - private void checkForBogusFieldNames(Node type, AnnotationValues<EqualsAndHashCode> annotation) { - if ( annotation.isExplicit("exclude") ) { - for ( int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().exclude()), type, true, true) ) { + private void checkForBogusFieldNames(EclipseNode type, AnnotationValues<EqualsAndHashCode> annotation) { + if (annotation.isExplicit("exclude")) { + for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().exclude()), type, true, true)) { annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i); } } - if ( annotation.isExplicit("of") ) { - for ( int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().of()), type, false, false) ) { + if (annotation.isExplicit("of")) { + for (int i : createListOfNonExistentFields(Arrays.asList(annotation.getInstance().of()), type, false, false)) { annotation.setWarning("of", "This field does not exist.", i); } } } - public void generateEqualsAndHashCodeForType(Node typeNode, Node errorNode) { - for ( Node child : typeNode.down() ) { - if ( child.getKind() == Kind.ANNOTATION ) { - if ( Eclipse.annotationTypeMatches(EqualsAndHashCode.class, child) ) { + public void generateEqualsAndHashCodeForType(EclipseNode typeNode, EclipseNode errorNode) { + for (EclipseNode child : typeNode.down()) { + if (child.getKind() == Kind.ANNOTATION) { + if (Eclipse.annotationTypeMatches(EqualsAndHashCode.class, child)) { //The annotation will make it happen, so we can skip it. return; } @@ -117,20 +117,21 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA generateMethods(typeNode, errorNode, null, null, null, false); } - @Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, Node annotationNode) { + @Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, + Annotation ast, EclipseNode annotationNode) { EqualsAndHashCode ann = annotation.getInstance(); List<String> excludes = Arrays.asList(ann.exclude()); List<String> includes = Arrays.asList(ann.of()); - Node typeNode = annotationNode.up(); + EclipseNode typeNode = annotationNode.up(); checkForBogusFieldNames(typeNode, annotation); Boolean callSuper = ann.callSuper(); - if ( !annotation.isExplicit("callSuper") ) callSuper = null; - if ( !annotation.isExplicit("exclude") ) excludes = null; - if ( !annotation.isExplicit("of") ) includes = null; + if (!annotation.isExplicit("callSuper")) callSuper = null; + if (!annotation.isExplicit("exclude")) excludes = null; + if (!annotation.isExplicit("of")) includes = null; - if ( excludes != null && includes != null ) { + if (excludes != null && includes != null) { excludes = null; annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored."); } @@ -138,70 +139,70 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true); } - public boolean generateMethods(Node typeNode, Node errorNode, List<String> excludes, List<String> includes, + public boolean generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes, Boolean callSuper, boolean whineIfExists) { assert excludes == null || includes == null; TypeDeclaration typeDecl = null; - if ( typeNode.get() instanceof TypeDeclaration ) typeDecl = (TypeDeclaration) typeNode.get(); + if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); int modifiers = typeDecl == null ? 0 : typeDecl.modifiers; boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0; - if ( typeDecl == null || notAClass ) { + if (typeDecl == null || notAClass) { errorNode.addError("@EqualsAndHashCode is only supported on a class."); return false; } boolean implicitCallSuper = callSuper == null; - if ( callSuper == null ) { + if (callSuper == null) { try { callSuper = ((Boolean)EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue(); - } catch ( Exception ignore ) {} + } catch (Exception ignore) {} } boolean isDirectDescendantOfObject = true; - if ( typeDecl.superclass != null ) { + if (typeDecl.superclass != null) { String p = typeDecl.superclass.toString(); isDirectDescendantOfObject = p.equals("Object") || p.equals("java.lang.Object"); } - if ( isDirectDescendantOfObject && callSuper ) { + if (isDirectDescendantOfObject && callSuper) { errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless."); return true; } - if ( !isDirectDescendantOfObject && !callSuper && implicitCallSuper ) { + if (!isDirectDescendantOfObject && !callSuper && implicitCallSuper) { errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type."); } - List<Node> nodesForEquality = new ArrayList<Node>(); - if ( includes != null ) { - for ( Node child : typeNode.down() ) { - if ( child.getKind() != Kind.FIELD ) continue; + List<EclipseNode> nodesForEquality = new ArrayList<EclipseNode>(); + if (includes != null) { + for (EclipseNode child : typeNode.down()) { + if (child.getKind() != Kind.FIELD) continue; FieldDeclaration fieldDecl = (FieldDeclaration) child.get(); - if ( includes.contains(new String(fieldDecl.name)) ) nodesForEquality.add(child); + if (includes.contains(new String(fieldDecl.name))) nodesForEquality.add(child); } } else { - for ( Node child : typeNode.down() ) { - if ( child.getKind() != Kind.FIELD ) continue; + for (EclipseNode child : typeNode.down()) { + if (child.getKind() != Kind.FIELD) continue; FieldDeclaration fieldDecl = (FieldDeclaration) child.get(); //Skip static fields. - if ( (fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0 ) continue; + if ((fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0) continue; //Skip transient fields. - if ( (fieldDecl.modifiers & ClassFileConstants.AccTransient) != 0 ) continue; + if ((fieldDecl.modifiers & ClassFileConstants.AccTransient) != 0) continue; //Skip excluded fields. - if ( excludes != null && excludes.contains(new String(fieldDecl.name)) ) continue; + if (excludes != null && excludes.contains(new String(fieldDecl.name))) continue; //Skip fields that start with $. - if ( fieldDecl.name.length > 0 && fieldDecl.name[0] == '$' ) continue; + if (fieldDecl.name.length > 0 && fieldDecl.name[0] == '$') continue; nodesForEquality.add(child); } } - switch ( methodExists("hashCode", typeNode) ) { + switch (methodExists("hashCode", typeNode)) { case NOT_EXISTS: MethodDeclaration hashCode = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get()); injectMethod(typeNode, hashCode); @@ -210,13 +211,13 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA break; default: case EXISTS_BY_USER: - if ( whineIfExists ) { + if (whineIfExists) { errorNode.addWarning("Not generating hashCode(): A method with that name already exists"); } break; } - switch ( methodExists("equals", typeNode) ) { + switch (methodExists("equals", typeNode)) { case NOT_EXISTS: MethodDeclaration equals = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get()); injectMethod(typeNode, equals); @@ -225,7 +226,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA break; default: case EXISTS_BY_USER: - if ( whineIfExists ) { + if (whineIfExists) { errorNode.addWarning("Not generating equals(Object other): A method with that name already exists"); } break; @@ -234,7 +235,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return true; } - private MethodDeclaration createHashCode(Node type, Collection<Node> fields, boolean callSuper, ASTNode source) { + private MethodDeclaration createHashCode(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; @@ -263,7 +264,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA /* final int PRIME = 31; */ { /* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */ - if ( !isEmpty || callSuper ) { + if (!isEmpty || callSuper) { LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE); Eclipse.setGeneratedBy(primeDecl, source); primeDecl.modifiers |= Modifier.FINAL; @@ -287,7 +288,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA statements.add(resultDecl); } - if ( callSuper ) { + if (callSuper) { MessageSend callToSuper = new MessageSend(); Eclipse.setGeneratedBy(callToSuper, source); callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; @@ -298,11 +299,11 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } int tempCounter = 0; - for ( Node field : fields ) { + for (EclipseNode field : fields) { FieldDeclaration f = (FieldDeclaration) field.get(); char[] token = f.type.getLastToken(); - if ( f.type.dimensions() == 0 && token != null ) { - if ( Arrays.equals(TypeConstants.FLOAT, token) ) { + if (f.type.dimensions() == 0 && token != null) { + if (Arrays.equals(TypeConstants.FLOAT, token)) { /* Float.floatToIntBits(fieldName) */ MessageSend floatToIntBits = new MessageSend(); floatToIntBits.sourceStart = pS; floatToIntBits.sourceEnd = pE; @@ -311,7 +312,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA floatToIntBits.selector = "floatToIntBits".toCharArray(); floatToIntBits.arguments = new Expression[] { generateFieldReference(f.name, source) }; intoResult.add(floatToIntBits); - } else if ( Arrays.equals(TypeConstants.DOUBLE, token) ) { + } else if (Arrays.equals(TypeConstants.DOUBLE, token)) { /* longToIntForHashCode(Double.doubleToLongBits(fieldName)) */ MessageSend doubleToLongBits = new MessageSend(); doubleToLongBits.sourceStart = pS; doubleToLongBits.sourceEnd = pE; @@ -333,7 +334,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA SingleNameReference copy2 = new SingleNameReference(tempName, p); Eclipse.setGeneratedBy(copy2, source); intoResult.add(longToIntForHashCode(copy1, copy2, source)); - } else if ( Arrays.equals(TypeConstants.BOOLEAN, token) ) { + } else if (Arrays.equals(TypeConstants.BOOLEAN, token)) { /* booleanField ? 1231 : 1237 */ IntLiteral int1231 = new IntLiteral("1231".toCharArray(), pS, pE); Eclipse.setGeneratedBy(int1231, source); @@ -343,9 +344,9 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA generateFieldReference(f.name, source), int1231, int1237); Eclipse.setGeneratedBy(int1231or1237, source); intoResult.add(int1231or1237); - } else if ( Arrays.equals(TypeConstants.LONG, token) ) { + } else if (Arrays.equals(TypeConstants.LONG, token)) { intoResult.add(longToIntForHashCode(generateFieldReference(f.name, source), generateFieldReference(f.name, source), source)); - } else if ( BUILT_IN_TYPES.contains(new String(token)) ) { + } else if (BUILT_IN_TYPES.contains(new String(token))) { intoResult.add(generateFieldReference(f.name, source)); } else /* objects */ { /* this.fieldName == null ? 0 : this.fieldName.hashCode() */ @@ -366,13 +367,13 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(nullOrHashCode, source); intoResult.add(nullOrHashCode); } - } else if ( f.type.dimensions() > 0 && token != null ) { + } else if (f.type.dimensions() > 0 && token != null) { /* Arrays.deepHashCode(array) //just hashCode for simple arrays */ MessageSend arraysHashCodeCall = new MessageSend(); arraysHashCodeCall.sourceStart = pS; arraysHashCodeCall.sourceEnd = pE; Eclipse.setGeneratedBy(arraysHashCodeCall, source); arraysHashCodeCall.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); - if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token)) ) { + if (f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) { arraysHashCodeCall.selector = "deepHashCode".toCharArray(); } else { arraysHashCodeCall.selector = "hashCode".toCharArray(); @@ -384,7 +385,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA /* fold each intoResult entry into: result = result * PRIME + (item); */ { - for ( Expression ex : intoResult ) { + for (Expression ex : intoResult) { SingleNameReference resultRef = new SingleNameReference(RESULT, p); Eclipse.setGeneratedBy(resultRef, source); SingleNameReference primeRef = new SingleNameReference(PRIME, p); @@ -415,7 +416,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return method; } - private MethodDeclaration createEquals(Node type, Collection<Node> fields, boolean callSuper, ASTNode source) { + private MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source) { int pS = source.sourceStart; int pE = source.sourceEnd; long p = (long)pS << 32 | pE; @@ -441,7 +442,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA List<Statement> statements = new ArrayList<Statement>(); - /* if ( o == this ) return true; */ { + /* if (o == this) return true; */ { SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p); Eclipse.setGeneratedBy(oRef, source); ThisReference thisRef = new ThisReference(pS, pE); @@ -458,7 +459,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA statements.add(ifOtherEqualsThis); } - /* if ( o == null ) return false; */ { + /* if (o == null) return false; */ { SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p); Eclipse.setGeneratedBy(oRef, source); NullLiteral nullLiteral = new NullLiteral(pS, pE); @@ -475,7 +476,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA statements.add(ifOtherEqualsNull); } - /* if ( o.getClass() != getClass() ) return false; */ { + /* if (o.getClass() != getClass()) return false; */ { MessageSend otherGetClass = new MessageSend(); otherGetClass.sourceStart = pS; otherGetClass.sourceEnd = pE; Eclipse.setGeneratedBy(otherGetClass, source); @@ -501,8 +502,8 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA char[] otherN = "other".toCharArray(); - /* if ( !super.equals(o) ) return false; */ - if ( callSuper ) { + /* if (!super.equals(o)) return false; */ + if (callSuper) { MessageSend callToSuper = new MessageSend(); callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; Eclipse.setGeneratedBy(callToSuper, source); @@ -525,19 +526,19 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA TypeDeclaration typeDecl = (TypeDeclaration)type.get(); /* MyType<?> other = (MyType<?>) o; */ { - if ( !fields.isEmpty() ) { + if (!fields.isEmpty()) { LocalDeclaration other = new LocalDeclaration(otherN, pS, pE); Eclipse.setGeneratedBy(other, source); char[] typeName = typeDecl.name; Expression targetType; - if ( typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0 ) { + if (typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0) { targetType = new SingleNameReference(((TypeDeclaration)type.get()).name, p); Eclipse.setGeneratedBy(targetType, source); other.type = new SingleTypeReference(typeName, p); Eclipse.setGeneratedBy(other.type, source); } else { TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length]; - for ( int i = 0 ; i < typeArgs.length ; i++ ) { + for (int i = 0; i < typeArgs.length; i++) { typeArgs[i] = new Wildcard(Wildcard.UNBOUND); typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE; Eclipse.setGeneratedBy(typeArgs[i], source); @@ -555,15 +556,15 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } } - for ( Node field : fields ) { + for (EclipseNode field : fields) { FieldDeclaration f = (FieldDeclaration) field.get(); char[] token = f.type.getLastToken(); - if ( f.type.dimensions() == 0 && token != null ) { - if ( Arrays.equals(TypeConstants.FLOAT, token) ) { + if (f.type.dimensions() == 0 && token != null) { + if (Arrays.equals(TypeConstants.FLOAT, token)) { statements.add(generateCompareFloatOrDouble(otherN, "Float".toCharArray(), f.name, source)); - } else if ( Arrays.equals(TypeConstants.DOUBLE, token) ) { + } else if (Arrays.equals(TypeConstants.DOUBLE, token)) { statements.add(generateCompareFloatOrDouble(otherN, "Double".toCharArray(), f.name, source)); - } else if ( BUILT_IN_TYPES.contains(new String(token)) ) { + } else if (BUILT_IN_TYPES.contains(new String(token))) { NameReference fieldRef = new SingleNameReference(f.name, p); Eclipse.setGeneratedBy(fieldRef, source); EqualExpression fieldsNotEqual = new EqualExpression(fieldRef, @@ -608,12 +609,12 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(ifStatement, source); statements.add(ifStatement); } - } else if ( f.type.dimensions() > 0 && token != null ) { + } else if (f.type.dimensions() > 0 && token != null) { MessageSend arraysEqualCall = new MessageSend(); arraysEqualCall.sourceStart = pS; arraysEqualCall.sourceEnd = pE; Eclipse.setGeneratedBy(arraysEqualCall, source); arraysEqualCall.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); - if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token)) ) { + if (f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) { arraysEqualCall.selector = "deepEquals".toCharArray(); } else { arraysEqualCall.selector = "equals".toCharArray(); @@ -648,7 +649,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA private IfStatement generateCompareFloatOrDouble(char[] otherN, char[] floatOrDouble, char[] fieldName, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; - /* if ( Float.compare(fieldName, other.fieldName) != 0 ) return false */ + /* if (Float.compare(fieldName, other.fieldName) != 0) return false */ MessageSend floatCompare = new MessageSend(); floatCompare.sourceStart = pS; floatCompare.sourceEnd = pE; Eclipse.setGeneratedBy(floatCompare, source); @@ -707,7 +708,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA NameReference ref; - if ( varNames.length > 1 ) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE); + if (varNames.length > 1) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE); else ref = new SingleNameReference(varNames[0], p); Eclipse.setGeneratedBy(ref, source); return ref; |