diff options
author | gsaul <gsaul@google.com> | 2019-08-15 13:39:20 -0700 |
---|---|---|
committer | David P. Baker <dpb@google.com> | 2019-08-19 12:23:56 -0400 |
commit | c35f5c3a7490cff1e307d65c49a4447140d47195 (patch) | |
tree | e5c6e3da2919b8af9c9803715ef7eba45bffe270 /factory | |
parent | e63019a49c2081c61595c36e499ab244aa82c40b (diff) | |
download | auto-c35f5c3a7490cff1e307d65c49a4447140d47195.tar.gz |
Prevent stack overflow caused by self referencing types (ex: E extends Enum<E>).
RELNOTES="Prevent stack overflow caused by self referencing types (ex: E extends Enum<E>)."
#AutoFactory
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=263631678
Diffstat (limited to 'factory')
3 files changed, 62 insertions, 27 deletions
diff --git a/factory/src/it/functional/src/main/java/com/google/auto/factory/GenericFoo.java b/factory/src/it/functional/src/main/java/com/google/auto/factory/GenericFoo.java index 94ee8a5b..f7c13b41 100644 --- a/factory/src/it/functional/src/main/java/com/google/auto/factory/GenericFoo.java +++ b/factory/src/it/functional/src/main/java/com/google/auto/factory/GenericFoo.java @@ -19,18 +19,24 @@ import java.util.List; import javax.inject.Provider; @AutoFactory -public class GenericFoo<A, B extends List<? extends A>, C> { +public class GenericFoo<A, B extends List<? extends A>, C, E extends Enum<E>> { private final A depA; private final B depB; private final IntAccessor depDIntAccessor; private final StringAccessor depDStringAccessor; + private final E depE; - <D extends IntAccessor & StringAccessor> GenericFoo(@Provided Provider<A> depA, B depB, D depD) { + <D extends IntAccessor & StringAccessor> GenericFoo( + @Provided Provider<A> depA, + B depB, + D depD, + E depE) { this.depA = depA.get(); this.depB = depB; this.depDIntAccessor = depD; this.depDStringAccessor = depD; + this.depE = depE; } public A getDepA() { @@ -53,9 +59,18 @@ public class GenericFoo<A, B extends List<? extends A>, C> { return depDStringAccessor; } + public E getDepE() { + return depE; + } + public interface IntAccessor {} public interface StringAccessor {} public interface IntAndStringAccessor extends IntAccessor, StringAccessor {} + + public enum DepE { + VALUE_1, + VALUE_2 + } } diff --git a/factory/src/it/functional/src/test/java/com/google/auto/factory/DependencyInjectionIntegrationTest.java b/factory/src/it/functional/src/test/java/com/google/auto/factory/DependencyInjectionIntegrationTest.java index 21ccfbb4..ebd83367 100644 --- a/factory/src/it/functional/src/test/java/com/google/auto/factory/DependencyInjectionIntegrationTest.java +++ b/factory/src/it/functional/src/test/java/com/google/auto/factory/DependencyInjectionIntegrationTest.java @@ -2,6 +2,7 @@ package com.google.auto.factory; import static com.google.common.truth.Truth.assertThat; +import com.google.auto.factory.GenericFoo.DepE; import com.google.auto.factory.GenericFoo.IntAndStringAccessor; import com.google.common.collect.ImmutableList; import com.google.inject.Guice; @@ -40,18 +41,19 @@ public class DependencyInjectionIntegrationTest { public void daggerInjectedGenericFactory() { GenericFooFactory<Number> genericFooFactory = DaggerFactoryComponent.create().generatedFactory(); - GenericFoo<Number, ImmutableList<Long>, String> three = - genericFooFactory.create(ImmutableList.of(3L), INT_AND_STRING_ACCESSOR); + GenericFoo<Number, ImmutableList<Long>, String, DepE> three = + genericFooFactory.create(ImmutableList.of(3L), INT_AND_STRING_ACCESSOR, DepE.VALUE_1); ArrayList<Double> intAndStringAccessorArrayList = new ArrayList<>(); intAndStringAccessorArrayList.add(4.0); - GenericFoo<Number, ArrayList<Double>, Long> four = - genericFooFactory.create(intAndStringAccessorArrayList, INT_AND_STRING_ACCESSOR); + GenericFoo<Number, ArrayList<Double>, Long, DepE> four = genericFooFactory.create( + intAndStringAccessorArrayList, INT_AND_STRING_ACCESSOR, DepE.VALUE_2); assertThat(three.getDepA()).isEqualTo(3); ImmutableList<Long> unusedLongList = three.getDepB(); assertThat(three.getDepB()).containsExactly(3L); assertThat(three.getDepDIntAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(three.getDepDStringAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(three.passThrough("value")).isEqualTo("value"); + assertThat(three.getDepE()).isEqualTo(DepE.VALUE_1); assertThat(four.getDepA()).isEqualTo(3); ArrayList<Double> unusedDoubleList = four.getDepB(); assertThat(four.getDepB()).isInstanceOf(ArrayList.class); @@ -59,6 +61,7 @@ public class DependencyInjectionIntegrationTest { assertThat(four.getDepDIntAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(four.getDepDStringAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(four.passThrough(5L)).isEqualTo(5L); + assertThat(four.getDepE()).isEqualTo(DepE.VALUE_2); } @Test public void guiceInjectedFactory() { @@ -85,23 +88,25 @@ public class DependencyInjectionIntegrationTest { GenericFooFactory<Number> genericFooFactory = Guice.createInjector(new GuiceModule()) .getInstance(Key.get(new TypeLiteral<GenericFooFactory<Number>>() {})); - GenericFoo<Number, ImmutableList<Long>, String> three = - genericFooFactory.create(ImmutableList.of(3L), INT_AND_STRING_ACCESSOR); + GenericFoo<Number, ImmutableList<Long>, String, DepE> three = + genericFooFactory.create(ImmutableList.of(3L), INT_AND_STRING_ACCESSOR, DepE.VALUE_1); ArrayList<Double> intAndStringAccessorArrayList = new ArrayList<>(); intAndStringAccessorArrayList.add(4.0); - GenericFoo<Number, ArrayList<Double>, Long> four = - genericFooFactory.create(intAndStringAccessorArrayList, INT_AND_STRING_ACCESSOR); + GenericFoo<Number, ArrayList<Double>, Long, DepE> four = genericFooFactory.create( + intAndStringAccessorArrayList, INT_AND_STRING_ACCESSOR, DepE.VALUE_2); assertThat(three.getDepA()).isEqualTo(3); ImmutableList<Long> unusedLongList = three.getDepB(); assertThat(three.getDepB()).containsExactly(3L); assertThat(three.getDepDIntAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(three.getDepDStringAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(three.passThrough("value")).isEqualTo("value"); + assertThat(three.getDepE()).isEqualTo(DepE.VALUE_1); assertThat(four.getDepA()).isEqualTo(3); ArrayList<Double> unusedDoubleList = four.getDepB(); assertThat(four.getDepB()).containsExactly(4.0); assertThat(four.getDepDIntAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(four.getDepDStringAccessor()).isEqualTo(INT_AND_STRING_ACCESSOR); assertThat(four.passThrough(5L)).isEqualTo(5L); + assertThat(four.getDepE()).isEqualTo(DepE.VALUE_2); } } diff --git a/factory/src/main/java/com/google/auto/factory/processor/TypeVariables.java b/factory/src/main/java/com/google/auto/factory/processor/TypeVariables.java index 35206c29..1f894732 100644 --- a/factory/src/main/java/com/google/auto/factory/processor/TypeVariables.java +++ b/factory/src/main/java/com/google/auto/factory/processor/TypeVariables.java @@ -18,6 +18,9 @@ package com.google.auto.factory.processor; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.ImmutableSet; +import java.util.HashSet; +import java.util.Set; +import javax.lang.model.element.Element; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.IntersectionType; @@ -32,11 +35,12 @@ final class TypeVariables { static ImmutableSet<TypeVariable> getReferencedTypeVariables(TypeMirror type) { checkNotNull(type); - return type.accept(ReferencedTypeVariables.INSTANCE, null); + return type.accept(ReferencedTypeVariables.INSTANCE, new HashSet<>()); } - private static final class ReferencedTypeVariables - extends SimpleTypeVisitor8<ImmutableSet<TypeVariable>, Void> { + private static final class ReferencedTypeVariables extends + SimpleTypeVisitor8<ImmutableSet<TypeVariable>, Set<Element>> { + private static final ReferencedTypeVariables INSTANCE = new ReferencedTypeVariables(); ReferencedTypeVariables() { @@ -44,56 +48,67 @@ final class TypeVariables { } @Override - public ImmutableSet<TypeVariable> visitArray(ArrayType t, Void unused) { - return t.getComponentType().accept(this, unused); + public ImmutableSet<TypeVariable> visitArray(ArrayType t, Set<Element> visited) { + return t.getComponentType().accept(this, visited); } @Override - public ImmutableSet<TypeVariable> visitDeclared(DeclaredType t, Void unused) { + public ImmutableSet<TypeVariable> visitDeclared( + DeclaredType t, Set<Element> visited) { + if (!visited.add(t.asElement())) { + return ImmutableSet.of(); + } ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); for (TypeMirror typeArgument : t.getTypeArguments()) { - typeVariables.addAll(typeArgument.accept(this, unused)); + typeVariables.addAll(typeArgument.accept(this, visited)); } return typeVariables.build(); } @Override - public ImmutableSet<TypeVariable> visitTypeVariable(TypeVariable t, Void unused) { + public ImmutableSet<TypeVariable> visitTypeVariable( + TypeVariable t, Set<Element> visited) { + if (!visited.add(t.asElement())) { + return ImmutableSet.of(); + } ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); typeVariables.add(t); - typeVariables.addAll(t.getLowerBound().accept(this, unused)); - typeVariables.addAll(t.getUpperBound().accept(this, unused)); + typeVariables.addAll(t.getLowerBound().accept(this, visited)); + typeVariables.addAll(t.getUpperBound().accept(this, visited)); return typeVariables.build(); } @Override - public ImmutableSet<TypeVariable> visitUnion(UnionType t, Void unused) { + public ImmutableSet<TypeVariable> visitUnion( + UnionType t, Set<Element> visited) { ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); for (TypeMirror unionType : t.getAlternatives()) { - typeVariables.addAll(unionType.accept(this, unused)); + typeVariables.addAll(unionType.accept(this, visited)); } return typeVariables.build(); } @Override - public ImmutableSet<TypeVariable> visitIntersection(IntersectionType t, Void unused) { + public ImmutableSet<TypeVariable> visitIntersection( + IntersectionType t, Set<Element> visited) { ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); for (TypeMirror intersectionType : t.getBounds()) { - typeVariables.addAll(intersectionType.accept(this, unused)); + typeVariables.addAll(intersectionType.accept(this, visited)); } return typeVariables.build(); } @Override - public ImmutableSet<TypeVariable> visitWildcard(WildcardType t, Void unused) { + public ImmutableSet<TypeVariable> visitWildcard( + WildcardType t, Set<Element> visited) { ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder(); TypeMirror extendsBound = t.getExtendsBound(); if (extendsBound != null) { - typeVariables.addAll(extendsBound.accept(this, unused)); + typeVariables.addAll(extendsBound.accept(this, visited)); } TypeMirror superBound = t.getSuperBound(); if (superBound != null) { - typeVariables.addAll(superBound.accept(this, unused)); + typeVariables.addAll(superBound.accept(this, visited)); } return typeVariables.build(); } |