diff options
6 files changed, 121 insertions, 31 deletions
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java index 0d0f51db..75339f7c 100644 --- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java @@ -475,47 +475,62 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH public TypeReference createTypeReference(EclipseNode type, long p, ASTNode source, boolean addWildcards) { int pS = source.sourceStart; int pE = source.sourceEnd; List<String> list = new ArrayList<String>(); + List<Integer> genericsCount = addWildcards ? new ArrayList<Integer>() : null; + list.add(type.getName()); + if (addWildcards) genericsCount.add(arraySizeOf(((TypeDeclaration) type.get()).typeParameters)); + boolean staticContext = (((TypeDeclaration) type.get()).modifiers & Modifier.STATIC) != 0; EclipseNode tNode = type.up(); + while (tNode != null && tNode.getKind() == Kind.TYPE) { list.add(tNode.getName()); + if (addWildcards) genericsCount.add(staticContext ? 0 : arraySizeOf(((TypeDeclaration) tNode.get()).typeParameters)); + if (!staticContext) staticContext = (((TypeDeclaration) tNode.get()).modifiers & Modifier.STATIC) != 0; tNode = tNode.up(); } Collections.reverse(list); - - TypeDeclaration typeDecl = (TypeDeclaration) type.get(); - int typeParamCount = typeDecl.typeParameters == null ? 0 : typeDecl.typeParameters.length; - if (typeParamCount == 0) addWildcards = false; - TypeReference[] typeArgs = null; - if (addWildcards) { - typeArgs = new TypeReference[typeParamCount]; - for (int i = 0; i < typeParamCount; i++) { - typeArgs[i] = new Wildcard(Wildcard.UNBOUND); - typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE; - setGeneratedBy(typeArgs[i], source); - } - } + if (addWildcards) Collections.reverse(genericsCount); if (list.size() == 1) { - if (addWildcards) { - return new ParameterizedSingleTypeReference(list.get(0).toCharArray(), typeArgs, 0, p); - } else { + if (!addWildcards || genericsCount.get(0) == 0) { return new SingleTypeReference(list.get(0).toCharArray(), p); + } else { + return new ParameterizedSingleTypeReference(list.get(0).toCharArray(), wildcardify(pS, pE, source, genericsCount.get(0)), 0, p); } } + + if (addWildcards) { + addWildcards = false; + for (int i : genericsCount) if (i > 0) addWildcards = true; + } + long[] ps = new long[list.size()]; char[][] tokens = new char[list.size()][]; for (int i = 0; i < list.size(); i++) { ps[i] = p; tokens[i] = list.get(i).toCharArray(); } - if (addWildcards) { - TypeReference[][] typeArgs2 = new TypeReference[tokens.length][]; - typeArgs2[typeArgs2.length - 1] = typeArgs; - return new ParameterizedQualifiedTypeReference(tokens, typeArgs2, 0, ps); - } else { - return new QualifiedTypeReference(tokens, ps); + + if (!addWildcards) return new QualifiedTypeReference(tokens, ps); + TypeReference[][] typeArgs2 = new TypeReference[tokens.length][]; + for (int i = 0; i < tokens.length; i++) typeArgs2[i] = wildcardify(pS, pE, source, genericsCount.get(i)); + return new ParameterizedQualifiedTypeReference(tokens, typeArgs2, 0, ps); + } + + private TypeReference[] wildcardify(int pS, int pE, ASTNode source, int count) { + if (count == 0) return null; + TypeReference[] typeArgs = new TypeReference[count]; + for (int i = 0; i < count; i++) { + typeArgs[i] = new Wildcard(Wildcard.UNBOUND); + typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE; + setGeneratedBy(typeArgs[i], source); } + + return typeArgs; + } + + private int arraySizeOf(Object[] arr) { + return arr == null ? 0 : arr.length; } public MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess, boolean needsCanEqual, List<Annotation> onParam) { @@ -683,7 +698,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH } else /* objects */ { /* final java.lang.Object this$fieldName = this.fieldName; */ /* final java.lang.Object other$fieldName = other.fieldName; */ - /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false;; */ + /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */ char[] thisDollarFieldName = ("this$" + field.getName()).toCharArray(); char[] otherDollarFieldName = ("other$" + field.getName()).toCharArray(); diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index da2db909..d8bfd154 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -371,31 +371,44 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas public JCExpression createTypeReference(JavacNode type, boolean addWildcards) { java.util.List<String> list = new ArrayList<String>(); + java.util.List<Integer> genericsCount = addWildcards ? new ArrayList<Integer>() : null; + list.add(type.getName()); + if (addWildcards) genericsCount.add(((JCClassDecl) type.get()).typarams.size()); + boolean staticContext = (((JCClassDecl) type.get()).getModifiers().flags & Flags.STATIC) != 0; JavacNode tNode = type.up(); + while (tNode != null && tNode.getKind() == Kind.TYPE) { list.add(tNode.getName()); + if (addWildcards) genericsCount.add(staticContext ? 0 : ((JCClassDecl) tNode.get()).typarams.size()); + if (!staticContext) staticContext = (((JCClassDecl) tNode.get()).getModifiers().flags & Flags.STATIC) != 0; tNode = tNode.up(); } Collections.reverse(list); - JCClassDecl typeDecl = (JCClassDecl) type.get(); + if (addWildcards) Collections.reverse(genericsCount); JavacTreeMaker maker = type.getTreeMaker(); JCExpression chain = maker.Ident(type.toName(list.get(0))); + if (addWildcards) chain = wildcardify(maker, chain, genericsCount.get(0)); for (int i = 1; i < list.size(); i++) { chain = maker.Select(chain, type.toName(list.get(i))); + if (addWildcards) chain = wildcardify(maker, chain, genericsCount.get(i)); } - if (!addWildcards || typeDecl.typarams.length() == 0) return chain; + return chain; + } + + private JCExpression wildcardify(JavacTreeMaker maker, JCExpression expr, int count) { + if (count == 0) return expr; ListBuffer<JCExpression> wildcards = new ListBuffer<JCExpression>(); - for (int i = 0 ; i < typeDecl.typarams.length() ; i++) { + for (int i = 0 ; i < count ; i++) { wildcards.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null)); } - return maker.TypeApply(chain, wildcards.toList()); + return maker.TypeApply(expr, wildcards.toList()); } public JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source, List<JCAnnotation> onParam) { diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java b/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java new file mode 100644 index 00000000..501d45a1 --- /dev/null +++ b/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java @@ -0,0 +1,28 @@ +public class EqualsAndHashCodeWithGenericsOnInners<A> { + class Inner<B> { + int x; + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof EqualsAndHashCodeWithGenericsOnInners.Inner)) return false; + final EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?> other = (EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?>) o; + if (!other.canEqual((java.lang.Object) this)) return false; + if (this.x != other.x) return false; + return true; + } + @java.lang.SuppressWarnings("all") + protected boolean canEqual(final java.lang.Object other) { + return other instanceof EqualsAndHashCodeWithGenericsOnInners.Inner; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.x; + return result; + } + } +} + diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeWithGenericsOnInners.java b/test/transform/resource/after-ecj/EqualsAndHashCodeWithGenericsOnInners.java new file mode 100644 index 00000000..164d0f15 --- /dev/null +++ b/test/transform/resource/after-ecj/EqualsAndHashCodeWithGenericsOnInners.java @@ -0,0 +1,32 @@ +public class EqualsAndHashCodeWithGenericsOnInners<A> { + @lombok.EqualsAndHashCode class Inner<B> { + int x; + Inner() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof EqualsAndHashCodeWithGenericsOnInners.Inner))) + return false; + final EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?> other = (EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?>) o; + if ((! other.canEqual((java.lang.Object) this))) + return false; + if ((this.x != other.x)) + return false; + return true; + } + protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) { + return (other instanceof EqualsAndHashCodeWithGenericsOnInners.Inner); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + final int PRIME = 59; + int result = 1; + result = ((result * PRIME) + this.x); + return result; + } + } + public EqualsAndHashCodeWithGenericsOnInners() { + super(); + } +} diff --git a/test/transform/resource/before/DataWithGenericsOnInners.java b/test/transform/resource/before/DataWithGenericsOnInners.java deleted file mode 100644 index c0afacee..00000000 --- a/test/transform/resource/before/DataWithGenericsOnInners.java +++ /dev/null @@ -1,4 +0,0 @@ -public class DataWithGenericsOnInners<A> { - @lombok.Data class Inner<B> {} -} - diff --git a/test/transform/resource/before/EqualsAndHashCodeWithGenericsOnInners.java b/test/transform/resource/before/EqualsAndHashCodeWithGenericsOnInners.java new file mode 100644 index 00000000..7af1d054 --- /dev/null +++ b/test/transform/resource/before/EqualsAndHashCodeWithGenericsOnInners.java @@ -0,0 +1,6 @@ +public class EqualsAndHashCodeWithGenericsOnInners<A> { + @lombok.EqualsAndHashCode class Inner<B> { + int x; + } +} + |