diff options
Diffstat (limited to 'factory')
8 files changed, 222 insertions, 12 deletions
diff --git a/factory/pom.xml b/factory/pom.xml index 629223a9..922cdbac 100644 --- a/factory/pom.xml +++ b/factory/pom.xml @@ -19,12 +19,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.sonatype.oss</groupId> - <artifactId>oss-parent</artifactId> - <version>7</version> - </parent> - <groupId>com.google.auto.factory</groupId> <artifactId>auto-factory</artifactId> <version>HEAD-SNAPSHOT</version> @@ -36,10 +30,10 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <auto-service.version>1.0</auto-service.version> - <auto-value.version>1.8.1</auto-value.version> + <auto-service.version>1.0.1</auto-service.version> + <auto-value.version>1.8.2</auto-value.version> <java.version>1.8</java.version> - <guava.version>30.1.1-jre</guava.version> + <guava.version>31.0.1-jre</guava.version> <truth.version>1.1.3</truth.version> </properties> @@ -67,11 +61,24 @@ <url>http://www.google.com</url> </organization> + <distributionManagement> + <snapshotRepository> + <id>sonatype-nexus-snapshots</id> + <name>Sonatype Nexus Snapshots</name> + <url>https://oss.sonatype.org/content/repositories/snapshots/</url> + </snapshotRepository> + <repository> + <id>sonatype-nexus-staging</id> + <name>Nexus Release Repository</name> + <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> + </repository> + </distributionManagement> + <dependencies> <dependency> <groupId>com.google.auto</groupId> <artifactId>auto-common</artifactId> - <version>1.1</version> + <version>1.2.1</version> </dependency> <dependency> <groupId>com.google.auto.value</groupId> @@ -170,7 +177,7 @@ <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-java</artifactId> - <version>1.0.7</version> + <version>1.1.0</version> </dependency> </dependencies> </plugin> diff --git a/factory/src/main/java/com/google/auto/factory/processor/FactoryWriter.java b/factory/src/main/java/com/google/auto/factory/processor/FactoryWriter.java index b7f9c3e4..8d6027dd 100644 --- a/factory/src/main/java/com/google/auto/factory/processor/FactoryWriter.java +++ b/factory/src/main/java/com/google/auto/factory/processor/FactoryWriter.java @@ -29,6 +29,7 @@ import static javax.lang.model.element.Modifier.STATIC; import com.google.auto.common.AnnotationMirrors; import com.google.auto.common.AnnotationValues; +import com.google.auto.common.MoreTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; @@ -59,6 +60,7 @@ import javax.lang.model.SourceVersion; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVariable; @@ -338,9 +340,28 @@ final class FactoryWriter { for (ProviderField provider : descriptor.providers().values()) { typeVariables.addAll(getReferencedTypeParameterNames(provider.key().type().get())); } + // If a parent type has a type parameter, like FooFactory<T>, then the generated factory needs + // to have the same parameter, like FooImplFactory<T> extends FooFactory<T>. This is a little + // approximate, at least in the case where there is more than one parent type that has a type + // parameter. But that should be pretty rare, so let's keep it simple for now. + typeVariables.addAll(typeVariablesFrom(descriptor.extendingType())); + for (TypeMirror implementing : descriptor.implementingTypes()) { + typeVariables.addAll(typeVariablesFrom(implementing)); + } return typeVariables.build(); } + private static List<TypeVariableName> typeVariablesFrom(TypeMirror type) { + if (type.getKind().equals(TypeKind.DECLARED)) { + DeclaredType declaredType = MoreTypes.asDeclared(type); + return declaredType.getTypeArguments().stream() + .filter(t -> t.getKind().equals(TypeKind.TYPEVAR)) + .map(t -> TypeVariableName.get(MoreTypes.asTypeVariable(t))) + .collect(toList()); + } + return ImmutableList.of(); + } + private static ImmutableSet<TypeVariableName> getMethodTypeVariables( FactoryMethodDescriptor methodDescriptor, ImmutableSet<TypeVariableName> factoryTypeVariables) { diff --git a/factory/src/main/java/com/google/auto/factory/processor/Key.java b/factory/src/main/java/com/google/auto/factory/processor/Key.java index 728149eb..6dc76445 100644 --- a/factory/src/main/java/com/google/auto/factory/processor/Key.java +++ b/factory/src/main/java/com/google/auto/factory/processor/Key.java @@ -97,7 +97,7 @@ abstract class Key { public final String toString() { String typeQualifiedName = MoreTypes.asTypeElement(type().get()).toString(); return qualifier().isPresent() - ? qualifier().get() + "/" + typeQualifiedName + ? AnnotationMirrors.toString(qualifier().get()) + "/" + typeQualifiedName : typeQualifiedName; } } diff --git a/factory/src/test/java/com/google/auto/factory/processor/AutoFactoryProcessorTest.java b/factory/src/test/java/com/google/auto/factory/processor/AutoFactoryProcessorTest.java index 0df4c9ca..2ab0fe95 100644 --- a/factory/src/test/java/com/google/auto/factory/processor/AutoFactoryProcessorTest.java +++ b/factory/src/test/java/com/google/auto/factory/processor/AutoFactoryProcessorTest.java @@ -508,6 +508,22 @@ public class AutoFactoryProcessorTest { .hasSourceEquivalentTo(loadExpectedFile("expected/DefaultPackageFactory.java")); } + @Test + public void generics() { + JavaFileObject file = JavaFileObjects.forResource("good/Generics.java"); + Compilation compilation = javac.compile(file); + assertThat(compilation).succeededWithoutWarnings(); + assertThat(compilation) + .generatedSourceFile("tests.Generics_FooImplFactory") + .hasSourceEquivalentTo(loadExpectedFile("expected/Generics_FooImplFactory.java")); + assertThat(compilation) + .generatedSourceFile("tests.Generics_ExplicitFooImplFactory") + .hasSourceEquivalentTo(loadExpectedFile("expected/Generics_ExplicitFooImplFactory.java")); + assertThat(compilation) + .generatedSourceFile("tests.Generics_FooImplWithClassFactory") + .hasSourceEquivalentTo(loadExpectedFile("expected/Generics_FooImplWithClassFactory.java")); + } + private JavaFileObject loadExpectedFile(String resourceName) { if (isJavaxAnnotationProcessingGeneratedAvailable()) { return JavaFileObjects.forResource(resourceName); diff --git a/factory/src/test/resources/expected/Generics_ExplicitFooImplFactory.java b/factory/src/test/resources/expected/Generics_ExplicitFooImplFactory.java new file mode 100644 index 00000000..00c6d92c --- /dev/null +++ b/factory/src/test/resources/expected/Generics_ExplicitFooImplFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright 2021 Google LLC + * + * 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 tests; + +import javax.annotation.processing.Generated; +import javax.inject.Inject; +import javax.inject.Provider; + +@Generated( + value = "com.google.auto.factory.processor.AutoFactoryProcessor", + comments = "https://github.com/google/auto/tree/master/factory" + ) +final class Generics_ExplicitFooImplFactory<M extends Generics.Bar> + implements Generics.FooFactory<M> { + private final Provider<M> unusedProvider; + + @Inject + Generics_ExplicitFooImplFactory(Provider<M> unusedProvider) { + this.unusedProvider = checkNotNull(unusedProvider, 1); + } + + @Override + public Generics.ExplicitFooImpl<M> create() { + return new Generics.ExplicitFooImpl<M>(checkNotNull(unusedProvider.get(), 1)); + } + + private static <T> T checkNotNull(T reference, int argumentIndex) { + if (reference == null) { + throw new NullPointerException( + "@AutoFactory method argument is null but is not marked @Nullable. Argument index: " + + argumentIndex); + } + return reference; + } +} diff --git a/factory/src/test/resources/expected/Generics_FooImplFactory.java b/factory/src/test/resources/expected/Generics_FooImplFactory.java new file mode 100644 index 00000000..2fb560a7 --- /dev/null +++ b/factory/src/test/resources/expected/Generics_FooImplFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2021 Google LLC + * + * 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 tests; + +import javax.annotation.processing.Generated; +import javax.inject.Inject; + +@Generated( + value = "com.google.auto.factory.processor.AutoFactoryProcessor", + comments = "https://github.com/google/auto/tree/master/factory" + ) +final class Generics_FooImplFactory<M extends Generics.Bar> implements Generics.FooFactory<M> { + @Inject + Generics_FooImplFactory() { + } + + @Override + public Generics.FooImpl<M> create() { + return new Generics.FooImpl<M>(); + } +} diff --git a/factory/src/test/resources/expected/Generics_FooImplWithClassFactory.java b/factory/src/test/resources/expected/Generics_FooImplWithClassFactory.java new file mode 100644 index 00000000..b338454f --- /dev/null +++ b/factory/src/test/resources/expected/Generics_FooImplWithClassFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2021 Google LLC + * + * 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 tests; + +import javax.annotation.processing.Generated; +import javax.inject.Inject; + +@Generated( + value = "com.google.auto.factory.processor.AutoFactoryProcessor", + comments = "https://github.com/google/auto/tree/master/factory" + ) +final class Generics_FooImplWithClassFactory<M extends Generics.Bar> extends Generics.FooFactoryClass<M> { + @Inject + Generics_FooImplWithClassFactory() { + } + + @Override + public Generics.FooImplWithClass<M> create() { + return new Generics.FooImplWithClass<M>(); + } +} diff --git a/factory/src/test/resources/good/Generics.java b/factory/src/test/resources/good/Generics.java new file mode 100644 index 00000000..638302fe --- /dev/null +++ b/factory/src/test/resources/good/Generics.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021 Google LLC + * + * 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 tests; + +import com.google.auto.factory.AutoFactory; +import com.google.auto.factory.Provided; + +class Generics { + interface Bar {} + + interface Foo<M extends Bar> {} + + interface FooFactory<M extends Bar> { + Foo<M> create(); + } + + // The generated FooImplFactory should also have an <M extends Bar> type parameter, so we can + // have FooImplFactory<M extends Bar> implements FooFactory<M>. + @AutoFactory(implementing = FooFactory.class) + static final class FooImpl<M extends Bar> implements Foo<M> { + FooImpl() {} + } + + // The generated ExplicitFooImplFactory should have an <M extends Bar> type parameter, which + // serves both for FooFactory<M> and for Provider<M> in the constructor. + @AutoFactory(implementing = FooFactory.class) + static final class ExplicitFooImpl<M extends Bar> implements Foo<M> { + ExplicitFooImpl(@Provided M unused) {} + } + + abstract static class FooFactoryClass<M extends Bar> { + abstract Foo<M> create(); + } + + @AutoFactory(extending = FooFactoryClass.class) + static final class FooImplWithClass<M extends Bar> implements Foo<M> {} +} |