diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/lombok/EqualsAndHashCode.java | 8 | ||||
-rw-r--r-- | src/core/lombok/ToString.java | 8 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 36 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java | 95 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleToString.java | 12 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java | 62 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleToString.java | 22 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 22 |
8 files changed, 156 insertions, 109 deletions
diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java index 88d72051..92fa42b5 100644 --- a/src/core/lombok/EqualsAndHashCode.java +++ b/src/core/lombok/EqualsAndHashCode.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -77,4 +77,10 @@ public @interface EqualsAndHashCode { * <strong>default: false</strong> */ boolean callSuper() default false; + + /** + * Normally, if getters are available, those are called. To suppress this and let the generated code use the fields directly, set this to {@code true}. + * <strong>default: false</strong> + */ + boolean doNotUseGetters() default false; } diff --git a/src/core/lombok/ToString.java b/src/core/lombok/ToString.java index 7b89d481..1247b7bb 100644 --- a/src/core/lombok/ToString.java +++ b/src/core/lombok/ToString.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -78,4 +78,10 @@ public @interface ToString { * <strong>default: false</strong> */ boolean callSuper() default false; + + /** + * Normally, if getters are available, those are called. To suppress this and let the generated code use the fields directly, set this to {@code true}. + * <strong>default: false</strong> + */ + boolean doNotUseGetters() default false; } diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index fc76ddc0..337ae3a8 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,16 +43,20 @@ import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.IfStatement; import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.NameReference; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; +import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; +import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.ThrowStatement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; @@ -94,6 +98,36 @@ public class EclipseHandlerUtil { } } + static TypeReference getFieldType(EclipseNode field, boolean useFieldsDirectly) { + return ((FieldDeclaration)field.get()).type; + } + + static Expression createFieldAccessor(EclipseNode field, boolean useFieldsDirectly, ASTNode source) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + FieldReference thisX = new FieldReference(field.getName().toCharArray(), p); + Eclipse.setGeneratedBy(thisX, source); + thisX.receiver = new ThisReference(pS, pE); + Eclipse.setGeneratedBy(thisX.receiver, source); + return thisX; + } + + static Expression createFieldAccessor(EclipseNode field, boolean useFieldsDirectly, ASTNode source, char[] receiver) { + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long)pS << 32 | pE; + + NameReference ref; + + char[][] tokens = new char[2][]; + tokens[0] = receiver; + tokens[1] = field.getName().toCharArray(); + long[] poss = {p, p}; + + ref = new QualifiedNameReference(tokens, poss, pS, pE); + Eclipse.setGeneratedBy(ref, source); + return ref; + } + /** * Checks if an eclipse-style array-of-array-of-characters to represent a fully qualified name ('foo.bar.baz'), matches a plain * string containing the same fully qualified name with dots in the string. diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index ef0bc9be..b7c6cda6 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,7 +46,6 @@ import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FalseLiteral; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; -import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.IfStatement; import org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; @@ -58,7 +57,6 @@ import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; -import org.eclipse.jdt.internal.compiler.ast.Reference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; @@ -114,7 +112,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } } - generateMethods(typeNode, errorNode, null, null, null, false); + generateMethods(typeNode, errorNode, null, null, null, false, false); } @Override public boolean handle(AnnotationValues<EqualsAndHashCode> annotation, @@ -136,11 +134,11 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored."); } - return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true); + return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, ann.doNotUseGetters()); } public boolean generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes, - Boolean callSuper, boolean whineIfExists) { + Boolean callSuper, boolean whineIfExists, boolean useFieldsDirectly) { assert excludes == null || includes == null; TypeDeclaration typeDecl = null; @@ -206,7 +204,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA switch (methodExists("equals", typeNode)) { case NOT_EXISTS: - MethodDeclaration equals = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get()); + MethodDeclaration equals = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(), useFieldsDirectly); injectMethod(typeNode, equals); break; case EXISTS_BY_LOMBOK: @@ -221,7 +219,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA switch (methodExists("hashCode", typeNode)) { case NOT_EXISTS: - MethodDeclaration hashCode = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get()); + MethodDeclaration hashCode = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(), useFieldsDirectly); injectMethod(typeNode, hashCode); break; case EXISTS_BY_LOMBOK: @@ -237,7 +235,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return true; } - private MethodDeclaration createHashCode(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source) { + private MethodDeclaration createHashCode(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, boolean useFieldsDirectly) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; @@ -302,9 +300,10 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA int tempCounter = 0; for (EclipseNode field : fields) { - FieldDeclaration f = (FieldDeclaration) field.get(); - char[] token = f.type.getLastToken(); - if (f.type.dimensions() == 0 && token != null) { + TypeReference fType = getFieldType(field, useFieldsDirectly); + char[] token = fType.getLastToken(); + Expression fieldAccessor = createFieldAccessor(field, useFieldsDirectly, source); + if (fType.dimensions() == 0 && token != null) { if (Arrays.equals(TypeConstants.FLOAT, token)) { /* Float.floatToIntBits(fieldName) */ MessageSend floatToIntBits = new MessageSend(); @@ -312,7 +311,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(floatToIntBits, source); floatToIntBits.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_FLOAT); floatToIntBits.selector = "floatToIntBits".toCharArray(); - floatToIntBits.arguments = new Expression[] { generateFieldReference(f.name, source) }; + floatToIntBits.arguments = new Expression[] { fieldAccessor }; intoResult.add(floatToIntBits); } else if (Arrays.equals(TypeConstants.DOUBLE, token)) { /* longToIntForHashCode(Double.doubleToLongBits(fieldName)) */ @@ -321,7 +320,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(doubleToLongBits, source); doubleToLongBits.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_DOUBLE); doubleToLongBits.selector = "doubleToLongBits".toCharArray(); - doubleToLongBits.arguments = new Expression[] { generateFieldReference(f.name, source) }; + doubleToLongBits.arguments = new Expression[] { fieldAccessor }; final char[] tempName = ("temp" + ++tempCounter).toCharArray(); LocalDeclaration tempVar = new LocalDeclaration(tempName, pS, pE); Eclipse.setGeneratedBy(tempVar, source); @@ -342,25 +341,23 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(int1231, source); IntLiteral int1237 = new IntLiteral("1237".toCharArray(), pS, pE); Eclipse.setGeneratedBy(int1237, source); - ConditionalExpression int1231or1237 = new ConditionalExpression( - generateFieldReference(f.name, source), int1231, int1237); + ConditionalExpression int1231or1237 = new ConditionalExpression(fieldAccessor, int1231, int1237); Eclipse.setGeneratedBy(int1231or1237, source); intoResult.add(int1231or1237); } else if (Arrays.equals(TypeConstants.LONG, token)) { - intoResult.add(longToIntForHashCode(generateFieldReference(f.name, source), generateFieldReference(f.name, source), source)); + intoResult.add(longToIntForHashCode(fieldAccessor, createFieldAccessor(field, useFieldsDirectly, source), source)); } else if (BUILT_IN_TYPES.contains(new String(token))) { - intoResult.add(generateFieldReference(f.name, source)); + intoResult.add(fieldAccessor); } else /* objects */ { /* this.fieldName == null ? 0 : this.fieldName.hashCode() */ MessageSend hashCodeCall = new MessageSend(); hashCodeCall.sourceStart = pS; hashCodeCall.sourceEnd = pE; Eclipse.setGeneratedBy(hashCodeCall, source); - hashCodeCall.receiver = generateFieldReference(f.name, source); + hashCodeCall.receiver = fieldAccessor; hashCodeCall.selector = "hashCode".toCharArray(); NullLiteral nullLiteral = new NullLiteral(pS, pE); Eclipse.setGeneratedBy(nullLiteral, source); - EqualExpression objIsNull = new EqualExpression( - generateFieldReference(f.name, source), nullLiteral, OperatorIds.EQUAL_EQUAL); + EqualExpression objIsNull = new EqualExpression(fieldAccessor, nullLiteral, OperatorIds.EQUAL_EQUAL); Eclipse.setGeneratedBy(objIsNull, source); IntLiteral int0 = new IntLiteral("0".toCharArray(), pS, pE); Eclipse.setGeneratedBy(int0, source); @@ -369,18 +366,18 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(nullOrHashCode, source); intoResult.add(nullOrHashCode); } - } else if (f.type.dimensions() > 0 && token != null) { + } else if (fType.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 (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) { arraysHashCodeCall.selector = "deepHashCode".toCharArray(); } else { arraysHashCodeCall.selector = "hashCode".toCharArray(); } - arraysHashCodeCall.arguments = new Expression[] { generateFieldReference(f.name, source) }; + arraysHashCodeCall.arguments = new Expression[] { fieldAccessor }; intoResult.add(arraysHashCodeCall); } } @@ -418,7 +415,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return method; } - private MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source) { + private MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, boolean useFieldsDirectly) { int pS = source.sourceStart; int pE = source.sourceEnd; long p = (long)pS << 32 | pE; @@ -559,17 +556,18 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } for (EclipseNode field : fields) { - FieldDeclaration f = (FieldDeclaration) field.get(); - char[] token = f.type.getLastToken(); + TypeReference fType = getFieldType(field, useFieldsDirectly); + char[] token = fType.getLastToken(); + Expression thisFieldAccessor = createFieldAccessor(field, useFieldsDirectly, source); + Expression otherFieldAccessor = createFieldAccessor(field, useFieldsDirectly, source, otherN); - if (f.type.dimensions() == 0 && token != null) { + if (fType.dimensions() == 0 && token != null) { if (Arrays.equals(TypeConstants.FLOAT, token)) { - statements.add(generateCompareFloatOrDouble(otherN, "Float".toCharArray(), f.name, source)); + statements.add(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, "Float".toCharArray(), source)); } else if (Arrays.equals(TypeConstants.DOUBLE, token)) { - statements.add(generateCompareFloatOrDouble(otherN, "Double".toCharArray(), f.name, source)); + statements.add(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, "Double".toCharArray(), source)); } else if (BUILT_IN_TYPES.contains(new String(token))) { - EqualExpression fieldsNotEqual = new EqualExpression(generateFieldReference(f.name, source), - generateQualifiedNameRef(source, otherN, f.name), OperatorIds.NOT_EQUAL); + EqualExpression fieldsNotEqual = new EqualExpression(thisFieldAccessor, otherFieldAccessor, OperatorIds.NOT_EQUAL); Eclipse.setGeneratedBy(fieldsNotEqual, source); FalseLiteral falseLiteral = new FalseLiteral(pS, pE); Eclipse.setGeneratedBy(falseLiteral, source); @@ -581,18 +579,16 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } else /* objects */ { NullLiteral nullLiteral = new NullLiteral(pS, pE); Eclipse.setGeneratedBy(nullLiteral, source); - EqualExpression fieldIsNull = new EqualExpression(generateFieldReference(f.name, source), nullLiteral, OperatorIds.EQUAL_EQUAL); + EqualExpression fieldIsNull = new EqualExpression(thisFieldAccessor, nullLiteral, OperatorIds.EQUAL_EQUAL); nullLiteral = new NullLiteral(pS, pE); Eclipse.setGeneratedBy(nullLiteral, source); - EqualExpression otherFieldIsntNull = new EqualExpression( - generateQualifiedNameRef(source, otherN, f.name), - nullLiteral, OperatorIds.NOT_EQUAL); + EqualExpression otherFieldIsntNull = new EqualExpression(otherFieldAccessor, nullLiteral, OperatorIds.NOT_EQUAL); MessageSend equalsCall = new MessageSend(); equalsCall.sourceStart = pS; equalsCall.sourceEnd = pE; Eclipse.setGeneratedBy(equalsCall, source); - equalsCall.receiver = generateFieldReference(f.name, source); + equalsCall.receiver = createFieldAccessor(field, useFieldsDirectly, source); equalsCall.selector = "equals".toCharArray(); - equalsCall.arguments = new Expression[] { generateQualifiedNameRef(source, otherN, f.name) }; + equalsCall.arguments = new Expression[] { createFieldAccessor(field, useFieldsDirectly, source, otherN) }; UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT); fieldsNotEqual.sourceStart = pS; fieldsNotEqual.sourceEnd = pE; Eclipse.setGeneratedBy(fieldsNotEqual, source); @@ -607,17 +603,17 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(ifStatement, source); statements.add(ifStatement); } - } else if (f.type.dimensions() > 0 && token != null) { + } else if (fType.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 (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) { arraysEqualCall.selector = "deepEquals".toCharArray(); } else { arraysEqualCall.selector = "equals".toCharArray(); } - arraysEqualCall.arguments = new Expression[] { generateFieldReference(f.name, source), generateQualifiedNameRef(source, otherN, f.name) }; + arraysEqualCall.arguments = new Expression[] { thisFieldAccessor, otherFieldAccessor }; UnaryExpression arraysNotEqual = new UnaryExpression(arraysEqualCall, OperatorIds.NOT); arraysNotEqual.sourceStart = pS; arraysNotEqual.sourceEnd = pE; Eclipse.setGeneratedBy(arraysNotEqual, source); @@ -642,7 +638,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return method; } - private IfStatement generateCompareFloatOrDouble(char[] otherN, char[] floatOrDouble, char[] fieldName, ASTNode source) { + private IfStatement generateCompareFloatOrDouble(Expression thisRef, Expression otherRef, char[] floatOrDouble, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; /* if (Float.compare(fieldName, other.fieldName) != 0) return false */ MessageSend floatCompare = new MessageSend(); @@ -650,7 +646,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA Eclipse.setGeneratedBy(floatCompare, source); floatCompare.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.LANG, floatOrDouble); floatCompare.selector = "compare".toCharArray(); - floatCompare.arguments = new Expression[] {generateFieldReference(fieldName, source), generateQualifiedNameRef(source, otherN, fieldName)}; + floatCompare.arguments = new Expression[] {thisRef, otherRef}; IntLiteral int0 = new IntLiteral(new char[] {'0'}, pS, pE); Eclipse.setGeneratedBy(int0, source); EqualExpression ifFloatCompareIsNot0 = new EqualExpression(floatCompare, int0, OperatorIds.NOT_EQUAL); @@ -666,7 +662,7 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA } /** Give 2 clones! */ - private Expression longToIntForHashCode(Reference ref1, Reference ref2, ASTNode source) { + private Expression longToIntForHashCode(Expression ref1, Expression ref2, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; /* (int)(ref >>> 32 ^ ref) */ IntLiteral int32 = new IntLiteral("32".toCharArray(), pS, pE); @@ -684,17 +680,6 @@ public class HandleEqualsAndHashCode implements EclipseAnnotationHandler<EqualsA return expr; } - private Reference generateFieldReference(char[] fieldName, ASTNode source) { - int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long)pS << 32 | pE; - FieldReference thisX = new FieldReference(fieldName, p); - Eclipse.setGeneratedBy(thisX, source); - thisX.receiver = new ThisReference(pS, pE); - Eclipse.setGeneratedBy(thisX.receiver, source); - thisX.token = fieldName; - return thisX; - } - private NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long)pS << 32 | pE; diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java index 5b87e32b..f409b5c4 100644 --- a/src/core/lombok/eclipse/handlers/HandleToString.java +++ b/src/core/lombok/eclipse/handlers/HandleToString.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -95,7 +95,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { try { includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue(); } catch (Exception ignore) {} - generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false); + generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, false); } public boolean handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) { @@ -116,11 +116,11 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { checkForBogusFieldNames(typeNode, annotation); - return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true); + return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, ann.doNotUseGetters()); } public boolean generateToString(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes, List<String> includes, - boolean includeFieldNames, Boolean callSuper, boolean whineIfExists) { + boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, boolean useFieldsDirectly) { TypeDeclaration typeDecl = null; if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); @@ -162,7 +162,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { switch (methodExists("toString", typeNode)) { case NOT_EXISTS: - MethodDeclaration toString = createToString(typeNode, nodesForToString, includeFieldNames, callSuper, errorNode.get()); + MethodDeclaration toString = createToString(typeNode, nodesForToString, includeFieldNames, callSuper, errorNode.get(), useFieldsDirectly); injectMethod(typeNode, toString); return true; case EXISTS_BY_LOMBOK: @@ -177,7 +177,7 @@ public class HandleToString implements EclipseAnnotationHandler<ToString> { } private MethodDeclaration createToString(EclipseNode type, Collection<EclipseNode> fields, - boolean includeFieldNames, boolean callSuper, ASTNode source) { + boolean includeFieldNames, boolean callSuper, ASTNode source, boolean useFieldsDirectly) { TypeDeclaration typeDeclaration = (TypeDeclaration)type.get(); char[] rawTypeName = typeDeclaration.name; String typeName = rawTypeName == null ? "" : new String(rawTypeName); diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 4ee24391..66d2308a 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -90,7 +90,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored."); } - return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true); + return generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, ann.doNotUseGetters()); } public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode errorNode) { @@ -103,11 +103,11 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } } - generateMethods(typeNode, errorNode, null, null, null, false); + generateMethods(typeNode, errorNode, null, null, null, false, false); } private boolean generateMethods(JavacNode typeNode, JavacNode errorNode, List<String> excludes, List<String> includes, - Boolean callSuper, boolean whineIfExists) { + Boolean callSuper, boolean whineIfExists, boolean useFieldsDirectly) { boolean notAClass = true; if (typeNode.get() instanceof JCClassDecl) { long flags = ((JCClassDecl)typeNode.get()).mods.flags; @@ -169,7 +169,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd switch (methodExists("equals", typeNode)) { case NOT_EXISTS: - JCMethodDecl method = createEquals(typeNode, nodesForEquality, callSuper); + JCMethodDecl method = createEquals(typeNode, nodesForEquality, callSuper, useFieldsDirectly); injectMethod(typeNode, method); break; case EXISTS_BY_LOMBOK: @@ -184,7 +184,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd switch (methodExists("hashCode", typeNode)) { case NOT_EXISTS: - JCMethodDecl method = createHashCode(typeNode, nodesForEquality, callSuper); + JCMethodDecl method = createHashCode(typeNode, nodesForEquality, callSuper, useFieldsDirectly); injectMethod(typeNode, method); break; case EXISTS_BY_LOMBOK: @@ -200,7 +200,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd return true; } - private JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper) { + private JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, boolean useFieldsDirectly) { TreeMaker maker = typeNode.getTreeMaker(); JCAnnotation overrideAnnotation = maker.Annotation(chainDots(maker, typeNode, "java", "lang", "Override"), List.<JCExpression>nil()); @@ -232,25 +232,23 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd int tempCounter = 0; for (JavacNode fieldNode : fields) { - JCVariableDecl field = (JCVariableDecl) fieldNode.get(); - JCExpression fType = field.vartype; - JCExpression thisDotField = maker.Select(maker.Ident(typeNode.toName("this")), field.name); - JCExpression thisDotFieldClone = maker.Select(maker.Ident(typeNode.toName("this")), field.name); + JCExpression fType = getFieldType(fieldNode, useFieldsDirectly); + JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, useFieldsDirectly); if (fType instanceof JCPrimitiveTypeTree) { switch (((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind()) { case BOOLEAN: /* this.fieldName ? 1231 : 1237 */ - intoResult = intoResult.append(maker.Conditional(thisDotField, maker.Literal(1231), maker.Literal(1237))); + intoResult = intoResult.append(maker.Conditional(fieldAccessor, maker.Literal(1231), maker.Literal(1237))); break; case LONG: - intoResult = intoResult.append(longToIntForHashCode(maker, thisDotField, thisDotFieldClone)); + intoResult = intoResult.append(longToIntForHashCode(maker, fieldAccessor, createFieldAccessor(maker, fieldNode, useFieldsDirectly))); break; case FLOAT: /* Float.floatToIntBits(this.fieldName) */ intoResult = intoResult.append(maker.Apply( List.<JCExpression>nil(), chainDots(maker, typeNode, "java", "lang", "Float", "floatToIntBits"), - List.of(thisDotField))); + List.of(fieldAccessor))); break; case DOUBLE: /* longToIntForHashCode(Double.doubleToLongBits(this.fieldName)) */ @@ -258,7 +256,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd JCExpression init = maker.Apply( List.<JCExpression>nil(), chainDots(maker, typeNode, "java", "lang", "Double", "doubleToLongBits"), - List.of(thisDotField)); + List.of(fieldAccessor)); statements = statements.append( maker.VarDef(maker.Modifiers(Flags.FINAL), tempVar, maker.TypeIdent(TypeTags.LONG), init)); intoResult = intoResult.append(longToIntForHashCode(maker, maker.Ident(tempVar), maker.Ident(tempVar))); @@ -269,7 +267,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd case INT: case CHAR: /* just the field */ - intoResult = intoResult.append(thisDotField); + intoResult = intoResult.append(fieldAccessor); break; } } else if (fType instanceof JCArrayTypeTree) { @@ -280,12 +278,12 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd JCExpression hcMethod = chainDots(maker, typeNode, "java", "util", "Arrays", useDeepHC ? "deepHashCode" : "hashCode"); intoResult = intoResult.append( - maker.Apply(List.<JCExpression>nil(), hcMethod, List.of(thisDotField))); + maker.Apply(List.<JCExpression>nil(), hcMethod, List.of(fieldAccessor))); } else /* objects */ { /* this.fieldName == null ? 0 : this.fieldName.hashCode() */ - JCExpression hcCall = maker.Apply(List.<JCExpression>nil(), maker.Select(thisDotField, typeNode.toName("hashCode")), + JCExpression hcCall = maker.Apply(List.<JCExpression>nil(), maker.Select(fieldAccessor, typeNode.toName("hashCode")), List.<JCExpression>nil()); - JCExpression thisEqualsNull = maker.Binary(JCTree.EQ, thisDotField, maker.Literal(TypeTags.BOT, null)); + JCExpression thisEqualsNull = maker.Binary(JCTree.EQ, fieldAccessor, maker.Literal(TypeTags.BOT, null)); intoResult = intoResult.append( maker.Conditional(thisEqualsNull, maker.Literal(0), hcCall)); } @@ -316,7 +314,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd return maker.TypeCast(maker.TypeIdent(TypeTags.INT), xorBits); } - private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper) { + private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, boolean useFieldsDirectly) { TreeMaker maker = typeNode.getTreeMaker(); JCClassDecl type = (JCClassDecl) typeNode.get(); @@ -382,24 +380,23 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd } for (JavacNode fieldNode : fields) { - JCVariableDecl field = (JCVariableDecl) fieldNode.get(); - JCExpression fType = field.vartype; - JCExpression thisDotField = maker.Select(maker.Ident(thisName), field.name); - JCExpression otherDotField = maker.Select(maker.Ident(otherName), field.name); + JCExpression fType = getFieldType(fieldNode, useFieldsDirectly); + JCExpression thisFieldAccessor = createFieldAccessor(maker, fieldNode, useFieldsDirectly); + JCExpression otherFieldAccessor = createFieldAccessor(maker, fieldNode, useFieldsDirectly, maker.Ident(otherName)); if (fType instanceof JCPrimitiveTypeTree) { switch (((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind()) { case FLOAT: /* if (Float.compare(this.fieldName, other.fieldName) != 0) return false; */ - statements = statements.append(generateCompareFloatOrDouble(thisDotField, otherDotField, maker, typeNode, false)); + statements = statements.append(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, maker, typeNode, false)); break; case DOUBLE: /* if (Double(this.fieldName, other.fieldName) != 0) return false; */ - statements = statements.append(generateCompareFloatOrDouble(thisDotField, otherDotField, maker, typeNode, true)); + statements = statements.append(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, maker, typeNode, true)); break; default: /* if (this.fieldName != other.fieldName) return false; */ statements = statements.append( - maker.If(maker.Binary(JCTree.NE, thisDotField, otherDotField), returnBool(maker, false), null)); + maker.If(maker.Binary(JCTree.NE, thisFieldAccessor, otherFieldAccessor), returnBool(maker, false), null)); break; } } else if (fType instanceof JCArrayTypeTree) { @@ -409,15 +406,16 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd boolean useDeepEquals = multiDim || !primitiveArray; JCExpression eqMethod = chainDots(maker, typeNode, "java", "util", "Arrays", useDeepEquals ? "deepEquals" : "equals"); - List<JCExpression> args = List.of(thisDotField, otherDotField); + List<JCExpression> args = List.of(thisFieldAccessor, otherFieldAccessor); statements = statements.append(maker.If(maker.Unary(JCTree.NOT, maker.Apply(List.<JCExpression>nil(), eqMethod, args)), returnBool(maker, false), null)); } else /* objects */ { /* if (this.fieldName == null ? other.fieldName != null : !this.fieldName.equals(other.fieldName)) return false; */ - JCExpression thisEqualsNull = maker.Binary(JCTree.EQ, thisDotField, maker.Literal(TypeTags.BOT, null)); - JCExpression otherNotEqualsNull = maker.Binary(JCTree.NE, otherDotField, maker.Literal(TypeTags.BOT, null)); - JCExpression thisEqualsThat = maker.Apply( - List.<JCExpression>nil(), maker.Select(thisDotField, typeNode.toName("equals")), List.of(otherDotField)); + JCExpression thisEqualsNull = maker.Binary(JCTree.EQ, thisFieldAccessor, maker.Literal(TypeTags.BOT, null)); + JCExpression otherNotEqualsNull = maker.Binary(JCTree.NE, thisFieldAccessor, maker.Literal(TypeTags.BOT, null)); + JCExpression thisEqualsThat = maker.Apply(List.<JCExpression>nil(), + maker.Select(createFieldAccessor(maker, fieldNode, useFieldsDirectly), typeNode.toName("equals")), + List.of(createFieldAccessor(maker, fieldNode, useFieldsDirectly, maker.Ident(otherName)))); JCExpression fieldsAreNotEqual = maker.Conditional(thisEqualsNull, otherNotEqualsNull, maker.Unary(JCTree.NOT, thisEqualsThat)); statements = statements.append(maker.If(fieldsAreNotEqual, returnBool(maker, false), null)); } diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index cdba7558..7b1b3b81 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,7 +40,6 @@ import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; -import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; @@ -89,7 +88,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored."); } - return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true); + return generateToString(typeNode, annotationNode, excludes, includes, ann.includeFieldNames(), callSuper, true, ann.doNotUseGetters()); } public void generateToStringForType(JavacNode typeNode, JavacNode errorNode) { @@ -106,11 +105,11 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { try { includeFieldNames = ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue(); } catch (Exception ignore) {} - generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false); + generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, false); } private boolean generateToString(JavacNode typeNode, JavacNode errorNode, List<String> excludes, List<String> includes, - boolean includeFieldNames, Boolean callSuper, boolean whineIfExists) { + boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, boolean useFieldsDirectly) { boolean notAClass = true; if (typeNode.get() instanceof JCClassDecl) { long flags = ((JCClassDecl)typeNode.get()).mods.flags; @@ -151,7 +150,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { switch (methodExists("toString", typeNode)) { case NOT_EXISTS: - JCMethodDecl method = createToString(typeNode, nodesForToString, includeFieldNames, callSuper); + JCMethodDecl method = createToString(typeNode, nodesForToString, includeFieldNames, callSuper, useFieldsDirectly); injectMethod(typeNode, method); return true; case EXISTS_BY_LOMBOK: @@ -166,7 +165,7 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { } - private JCMethodDecl createToString(JavacNode typeNode, List<JavacNode> fields, boolean includeFieldNames, boolean callSuper) { + private JCMethodDecl createToString(JavacNode typeNode, List<JavacNode> fields, boolean includeFieldNames, boolean callSuper, boolean useFieldsDirectly) { TreeMaker maker = typeNode.getTreeMaker(); JCAnnotation overrideAnnotation = maker.Annotation(chainDots(maker, typeNode, "java", "lang", "Override"), List.<JCExpression>nil()); @@ -203,16 +202,16 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { JCVariableDecl field = (JCVariableDecl) fieldNode.get(); JCExpression expr; - JCFieldAccess thisX = maker.Select(maker.Ident(fieldNode.toName("this")), field.name); + JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, useFieldsDirectly); - if (field.vartype instanceof JCArrayTypeTree) { + if (getFieldType(fieldNode, useFieldsDirectly) instanceof JCArrayTypeTree) { boolean multiDim = ((JCArrayTypeTree)field.vartype).elemtype instanceof JCArrayTypeTree; boolean primitiveArray = ((JCArrayTypeTree)field.vartype).elemtype instanceof JCPrimitiveTypeTree; boolean useDeepTS = multiDim || !primitiveArray; JCExpression hcMethod = chainDots(maker, typeNode, "java", "util", "Arrays", useDeepTS ? "deepToString" : "toString"); - expr = maker.Apply(List.<JCExpression>nil(), hcMethod, List.<JCExpression>of(thisX)); - } else expr = thisX; + expr = maker.Apply(List.<JCExpression>nil(), hcMethod, List.<JCExpression>of(fieldAccessor)); + } else expr = fieldAccessor; if (first) { current = maker.Binary(JCTree.PLUS, current, expr); @@ -238,5 +237,4 @@ public class HandleToString implements JavacAnnotationHandler<ToString> { return maker.MethodDef(mods, typeNode.toName("toString"), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 9ac84bd1..84388c30 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright © 2009 Reinier Zwitserloot and Roel Spilker. + * Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -270,6 +270,26 @@ public class JavacHandlerUtil { } /** + * Creates an expression that reads the field. Will either be {@code this.field} or {@code this.getField()} depending on whether or not there's a getter. + */ + static JCExpression createFieldAccessor(TreeMaker maker, JavacNode field, boolean useFieldsDirectly) { + return createFieldAccessor(maker, field, useFieldsDirectly, maker.Ident(field.toName("this"))); + } + + static JCExpression createFieldAccessor(TreeMaker maker, JavacNode field, boolean useFieldsDirectly, JCExpression receiver) { + return maker.Select(receiver, ((JCVariableDecl)field.get()).name); + } + + /** + * Returns the type of the field, unless a getter exists for this field, in which case the return type of the getter is returned. + * + * @see #createFieldAccessor(TreeMaker, JavacNode) + */ + static JCExpression getFieldType(JavacNode field, boolean useFieldsDirectly) { + return ((JCVariableDecl)field.get()).vartype; + } + + /** * Adds the given new field declaration to the provided type AST Node. * * Also takes care of updating the JavacAST. |