aboutsummaryrefslogtreecommitdiff
path: root/factory/src/main/java/com/google/auto
diff options
context:
space:
mode:
Diffstat (limited to 'factory/src/main/java/com/google/auto')
-rw-r--r--factory/src/main/java/com/google/auto/factory/AutoFactory.java4
-rw-r--r--factory/src/main/java/com/google/auto/factory/Provided.java2
-rw-r--r--factory/src/main/java/com/google/auto/factory/package-info.java17
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/AnnotationValues.java28
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/AutoFactoryDeclaration.java88
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/AutoFactoryProcessor.java107
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/Elements2.java10
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptor.java88
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptorGenerator.java136
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/FactoryMethodDescriptor.java36
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/FactoryWriter.java103
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/ImplementationMethodDescriptor.java16
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/Key.java25
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/Mirrors.java53
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/Parameter.java23
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/ProvidedChecker.java66
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/ProviderField.java4
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/TypeVariables.java19
-rw-r--r--factory/src/main/java/com/google/auto/factory/processor/package-info.java3
19 files changed, 484 insertions, 344 deletions
diff --git a/factory/src/main/java/com/google/auto/factory/AutoFactory.java b/factory/src/main/java/com/google/auto/factory/AutoFactory.java
index 2ef84cc3..3b5d90ea 100644
--- a/factory/src/main/java/com/google/auto/factory/AutoFactory.java
+++ b/factory/src/main/java/com/google/auto/factory/AutoFactory.java
@@ -32,7 +32,7 @@ import java.lang.annotation.Target;
*
* @author Gregory Kick
*/
-@Target({ TYPE, CONSTRUCTOR })
+@Target({TYPE, CONSTRUCTOR})
public @interface AutoFactory {
/**
* The <i>simple</i> name of the generated factory; the factory is always generated in the same
@@ -50,7 +50,7 @@ public @interface AutoFactory {
/**
* A list of interfaces that the generated factory is required to implement.
*/
- Class<?>[] implementing() default { };
+ Class<?>[] implementing() default {};
/**
* The type that the generated factory is require to extend.
diff --git a/factory/src/main/java/com/google/auto/factory/Provided.java b/factory/src/main/java/com/google/auto/factory/Provided.java
index e81e4aa6..226a16f4 100644
--- a/factory/src/main/java/com/google/auto/factory/Provided.java
+++ b/factory/src/main/java/com/google/auto/factory/Provided.java
@@ -26,4 +26,4 @@ import java.lang.annotation.Target;
* @author Gregory Kick
*/
@Target(PARAMETER)
-public @interface Provided { }
+public @interface Provided {}
diff --git a/factory/src/main/java/com/google/auto/factory/package-info.java b/factory/src/main/java/com/google/auto/factory/package-info.java
new file mode 100644
index 00000000..ea1ddd88
--- /dev/null
+++ b/factory/src/main/java/com/google/auto/factory/package-info.java
@@ -0,0 +1,17 @@
+/*
+ * 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 com.google.auto.factory;
+
diff --git a/factory/src/main/java/com/google/auto/factory/processor/AnnotationValues.java b/factory/src/main/java/com/google/auto/factory/processor/AnnotationValues.java
index b767c47f..53d38a40 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/AnnotationValues.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/AnnotationValues.java
@@ -32,24 +32,29 @@ final class AnnotationValues {
static boolean asBoolean(AnnotationValue value) {
return value.accept(
new SimpleAnnotationValueVisitor6<Boolean, Void>() {
- @Override protected Boolean defaultAction(Object o, Void p) {
+ @Override
+ protected Boolean defaultAction(Object o, Void p) {
throw new IllegalArgumentException();
}
- @Override public Boolean visitBoolean(boolean b, Void p) {
+ @Override
+ public Boolean visitBoolean(boolean b, Void p) {
return b;
}
- }, null);
+ },
+ null);
}
static TypeElement asType(AnnotationValue value) {
return value.accept(
new SimpleAnnotationValueVisitor6<TypeElement, Void>() {
- @Override protected TypeElement defaultAction(Object o, Void p) {
+ @Override
+ protected TypeElement defaultAction(Object o, Void p) {
throw new IllegalArgumentException();
}
- @Override public TypeElement visitType(TypeMirror t, Void p) {
+ @Override
+ public TypeElement visitType(TypeMirror t, Void p) {
return t.accept(
new SimpleTypeVisitor6<TypeElement, Void>() {
@Override
@@ -59,12 +64,14 @@ final class AnnotationValues {
@Override
public TypeElement visitDeclared(DeclaredType t, Void p) {
- return Iterables.getOnlyElement(ElementFilter.typesIn(
- ImmutableList.of(t.asElement())));
+ return Iterables.getOnlyElement(
+ ElementFilter.typesIn(ImmutableList.of(t.asElement())));
}
- }, null);
+ },
+ null);
}
- }, null);
+ },
+ null);
}
static ImmutableList<? extends AnnotationValue> asList(AnnotationValue value) {
@@ -80,6 +87,7 @@ final class AnnotationValues {
List<? extends AnnotationValue> vals, Void p) {
return ImmutableList.copyOf(vals);
}
- }, null);
+ },
+ null);
}
}
diff --git a/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryDeclaration.java b/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryDeclaration.java
index e2da6eae..889d8e41 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryDeclaration.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryDeclaration.java
@@ -21,13 +21,13 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.getOnlyElement;
+import static java.util.Objects.requireNonNull;
import static javax.lang.model.element.ElementKind.PACKAGE;
import static javax.lang.model.util.ElementFilter.typesIn;
import static javax.tools.Diagnostic.Kind.ERROR;
import com.google.auto.factory.AutoFactory;
import com.google.auto.value.AutoValue;
-import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
@@ -36,6 +36,7 @@ import com.google.common.collect.ImmutableSet;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import javax.annotation.processing.Messager;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
@@ -54,12 +55,19 @@ import javax.lang.model.util.Elements;
@AutoValue
abstract class AutoFactoryDeclaration {
abstract TypeElement targetType();
+
abstract Element target();
+
abstract Optional<String> className();
+
abstract TypeElement extendingType();
+
abstract ImmutableSet<TypeElement> implementingTypes();
+
abstract boolean allowSubclasses();
+
abstract AnnotationMirror mirror();
+
abstract ImmutableMap<String, AnnotationValue> valuesMap();
PackageAndClass getFactoryName() {
@@ -97,52 +105,70 @@ abstract class AutoFactoryDeclaration {
Optional<AutoFactoryDeclaration> createIfValid(Element element) {
checkNotNull(element);
AnnotationMirror mirror = Mirrors.getAnnotationMirror(element, AutoFactory.class).get();
- checkArgument(Mirrors.getQualifiedName(mirror.getAnnotationType()).
- contentEquals(AutoFactory.class.getName()));
+ checkArgument(
+ Mirrors.getQualifiedName(mirror.getAnnotationType())
+ .contentEquals(AutoFactory.class.getName()));
Map<String, AnnotationValue> values =
Mirrors.simplifyAnnotationValueMap(elements.getElementValuesWithDefaults(mirror));
checkState(values.size() == 4);
- // className value is a string, so we can just call toString
- AnnotationValue classNameValue = values.get("className");
+ // className value is a string, so we can just call toString. We know values.get("className")
+ // is non-null because @AutoFactory has an annotation element of that name.
+ AnnotationValue classNameValue = requireNonNull(values.get("className"));
String className = classNameValue.getValue().toString();
if (!className.isEmpty() && !isValidIdentifier(className)) {
- messager.printMessage(ERROR,
+ messager.printMessage(
+ ERROR,
String.format("\"%s\" is not a valid Java identifier", className),
- element, mirror, classNameValue);
- return Optional.absent();
+ element,
+ mirror,
+ classNameValue);
+ return Optional.empty();
}
AnnotationValue extendingValue = checkNotNull(values.get("extending"));
TypeElement extendingType = AnnotationValues.asType(extendingValue);
if (extendingType == null) {
- messager.printMessage(ERROR, "Unable to find the type: "
- + extendingValue.getValue().toString(),
- element, mirror, extendingValue);
- return Optional.absent();
+ messager.printMessage(
+ ERROR,
+ "Unable to find the type: " + extendingValue.getValue(),
+ element,
+ mirror,
+ extendingValue);
+ return Optional.empty();
} else if (!isValidSupertypeForClass(extendingType)) {
- messager.printMessage(ERROR,
- String.format("%s is not a valid supertype for a factory. "
- + "Supertypes must be non-final classes.",
- extendingType.getQualifiedName()),
- element, mirror, extendingValue);
- return Optional.absent();
+ messager.printMessage(
+ ERROR,
+ String.format(
+ "%s is not a valid supertype for a factory. "
+ + "Supertypes must be non-final classes.",
+ extendingType.getQualifiedName()),
+ element,
+ mirror,
+ extendingValue);
+ return Optional.empty();
}
ImmutableList<ExecutableElement> noParameterConstructors =
FluentIterable.from(ElementFilter.constructorsIn(extendingType.getEnclosedElements()))
- .filter(new Predicate<ExecutableElement>() {
- @Override public boolean apply(ExecutableElement constructor) {
- return constructor.getParameters().isEmpty();
- }
- })
+ .filter(
+ new Predicate<ExecutableElement>() {
+ @Override
+ public boolean apply(ExecutableElement constructor) {
+ return constructor.getParameters().isEmpty();
+ }
+ })
.toList();
- if (noParameterConstructors.size() == 0) {
- messager.printMessage(ERROR,
- String.format("%s is not a valid supertype for a factory. "
- + "Factory supertypes must have a no-arg constructor.",
- extendingType.getQualifiedName()),
- element, mirror, extendingValue);
- return Optional.absent();
+ if (noParameterConstructors.isEmpty()) {
+ messager.printMessage(
+ ERROR,
+ String.format(
+ "%s is not a valid supertype for a factory. "
+ + "Factory supertypes must have a no-arg constructor.",
+ extendingType.getQualifiedName()),
+ element,
+ mirror,
+ extendingValue);
+ return Optional.empty();
} else if (noParameterConstructors.size() > 1) {
throw new IllegalStateException("Multiple constructors with no parameters??");
}
@@ -161,7 +187,7 @@ abstract class AutoFactoryDeclaration {
new AutoValue_AutoFactoryDeclaration(
getAnnotatedType(element),
element,
- className.isEmpty() ? Optional.<String>absent() : Optional.of(className),
+ className.isEmpty() ? Optional.empty() : Optional.of(className),
extendingType,
implementingTypes,
allowSubclasses,
diff --git a/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryProcessor.java b/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryProcessor.java
index 5cc1d94d..82349f21 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryProcessor.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/AutoFactoryProcessor.java
@@ -19,7 +19,6 @@ import com.google.auto.common.MoreTypes;
import com.google.auto.factory.AutoFactory;
import com.google.auto.factory.Provided;
import com.google.auto.service.AutoService;
-import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
@@ -30,7 +29,9 @@ import com.google.common.collect.Iterables;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
@@ -83,8 +84,9 @@ public final class AutoFactoryProcessor extends AbstractProcessor {
try {
doProcess(roundEnv);
} catch (Throwable e) {
- messager.printMessage(Kind.ERROR, "Failed to process @AutoFactory annotations:\n"
- + Throwables.getStackTraceAsString(e));
+ messager.printMessage(
+ Kind.ERROR,
+ "Failed to process @AutoFactory annotations:\n" + Throwables.getStackTraceAsString(e));
}
return false;
}
@@ -127,49 +129,58 @@ public final class AutoFactoryProcessor extends AbstractProcessor {
simpleNamesToNames(indexedMethods.keySet());
FactoryWriter factoryWriter = new FactoryWriter(processingEnv, factoriesBeingCreated);
- indexedMethods.asMap().forEach(
- (factoryName, methodDescriptors) -> {
- // The sets of classes that are mentioned in the `extending` and `implementing` elements,
- // respectively, of the @AutoFactory annotations for this factory.
- ImmutableSet.Builder<TypeMirror> extending = newTypeSetBuilder();
- ImmutableSortedSet.Builder<TypeMirror> implementing = newTypeSetBuilder();
- boolean publicType = false;
- Boolean allowSubclasses = null;
- boolean skipCreation = false;
- for (FactoryMethodDescriptor methodDescriptor : methodDescriptors) {
- extending.add(methodDescriptor.declaration().extendingType().asType());
- for (TypeElement implementingType :
- methodDescriptor.declaration().implementingTypes()) {
- implementing.add(implementingType.asType());
- }
- publicType |= methodDescriptor.publicMethod();
- if (allowSubclasses == null) {
- allowSubclasses = methodDescriptor.declaration().allowSubclasses();
- } else if (!allowSubclasses.equals(methodDescriptor.declaration().allowSubclasses())) {
- skipCreation = true;
- messager.printMessage(Kind.ERROR,
- "Cannot mix allowSubclasses=true and allowSubclasses=false in one factory.",
- methodDescriptor.declaration().target(),
- methodDescriptor.declaration().mirror(),
- methodDescriptor.declaration().valuesMap().get("allowSubclasses"));
- }
- }
- if (!skipCreation) {
- try {
- factoryWriter.writeFactory(
- FactoryDescriptor.create(
- factoryName,
- Iterables.getOnlyElement(extending.build()),
- implementing.build(),
- publicType,
- ImmutableSet.copyOf(methodDescriptors),
- implementationMethodDescriptors.get(factoryName),
- allowSubclasses));
- } catch (IOException e) {
- messager.printMessage(Kind.ERROR, "failed: " + e);
- }
- }
- });
+ indexedMethods
+ .asMap()
+ .forEach(
+ (factoryName, methodDescriptors) -> {
+ if (methodDescriptors.isEmpty()) {
+ // This shouldn't happen, but check anyway to avoid an exception for
+ // methodDescriptors.iterator().next() below.
+ return;
+ }
+ // The sets of classes that are mentioned in the `extending` and `implementing`
+ // elements, respectively, of the @AutoFactory annotations for this factory.
+ ImmutableSet.Builder<TypeMirror> extending = newTypeSetBuilder();
+ ImmutableSortedSet.Builder<TypeMirror> implementing = newTypeSetBuilder();
+ boolean publicType = false;
+ Set<Boolean> allowSubclassesSet = new HashSet<>();
+ boolean skipCreation = false;
+ for (FactoryMethodDescriptor methodDescriptor : methodDescriptors) {
+ extending.add(methodDescriptor.declaration().extendingType().asType());
+ for (TypeElement implementingType :
+ methodDescriptor.declaration().implementingTypes()) {
+ implementing.add(implementingType.asType());
+ }
+ publicType |= methodDescriptor.publicMethod();
+ allowSubclassesSet.add(methodDescriptor.declaration().allowSubclasses());
+ if (allowSubclassesSet.size() > 1) {
+ skipCreation = true;
+ messager.printMessage(
+ Kind.ERROR,
+ "Cannot mix allowSubclasses=true and allowSubclasses=false in one factory.",
+ methodDescriptor.declaration().target(),
+ methodDescriptor.declaration().mirror(),
+ methodDescriptor.declaration().valuesMap().get("allowSubclasses"));
+ }
+ }
+ // The set can't be empty because we eliminated methodDescriptors.isEmpty() above.
+ boolean allowSubclasses = allowSubclassesSet.iterator().next();
+ if (!skipCreation) {
+ try {
+ factoryWriter.writeFactory(
+ FactoryDescriptor.create(
+ factoryName,
+ Iterables.getOnlyElement(extending.build()),
+ implementing.build(),
+ publicType,
+ ImmutableSet.copyOf(methodDescriptors),
+ implementationMethodDescriptors.get(factoryName),
+ allowSubclasses));
+ } catch (IOException e) {
+ messager.printMessage(Kind.ERROR, "failed: " + e);
+ }
+ }
+ });
}
private ImmutableSet<ImplementationMethodDescriptor> implementationMethods(
@@ -180,8 +191,7 @@ public final class AutoFactoryProcessor extends AbstractProcessor {
ElementFilter.methodsIn(elements.getAllMembers(supertype))) {
if (implementationMethod.getModifiers().contains(Modifier.ABSTRACT)) {
ExecutableType methodType =
- Elements2.getExecutableElementAsMemberOf(
- types, implementationMethod, supertype);
+ Elements2.getExecutableElementAsMemberOf(types, implementationMethod, supertype);
ImmutableSet<Parameter> passedParameters =
Parameter.forParameterList(
implementationMethod.getParameters(), methodType.getParameterTypes(), types);
@@ -192,6 +202,7 @@ public final class AutoFactoryProcessor extends AbstractProcessor {
.publicMethod()
.passedParameters(passedParameters)
.isVarArgs(implementationMethod.isVarArgs())
+ .exceptions(implementationMethod.getThrownTypes())
.build());
}
}
diff --git a/factory/src/main/java/com/google/auto/factory/processor/Elements2.java b/factory/src/main/java/com/google/auto/factory/processor/Elements2.java
index 30230f7f..3663f370 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/Elements2.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/Elements2.java
@@ -22,10 +22,10 @@ import static javax.lang.model.element.ElementKind.PACKAGE;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.STATIC;
+import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableSet;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
@@ -33,7 +33,7 @@ import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Types;
final class Elements2 {
- private Elements2() { }
+ private Elements2() {}
static ImmutableSet<ExecutableElement> getConstructors(TypeElement type) {
checkNotNull(type);
@@ -72,11 +72,11 @@ final class Elements2 {
throw new IllegalStateException(
"Expected subTypeElement.asType() to return a class/interface type.");
}
- TypeMirror subExecutableTypeMirror = types.asMemberOf(
- (DeclaredType) subTypeMirror, executableElement);
+ TypeMirror subExecutableTypeMirror =
+ types.asMemberOf(MoreTypes.asDeclared(subTypeMirror), executableElement);
if (!subExecutableTypeMirror.getKind().equals(TypeKind.EXECUTABLE)) {
throw new IllegalStateException("Expected subExecutableTypeMirror to be an executable type.");
}
- return (ExecutableType) subExecutableTypeMirror;
+ return MoreTypes.asExecutable(subExecutableTypeMirror);
}
}
diff --git a/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptor.java b/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptor.java
index 5ed2307a..019295f6 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptor.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptor.java
@@ -17,16 +17,15 @@ package com.google.auto.factory.processor;
import com.google.auto.value.AutoValue;
import com.google.common.base.CharMatcher;
-import com.google.common.base.Optional;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
-import java.util.Collection;
+import com.google.common.collect.Streams;
import java.util.HashSet;
-import java.util.Map.Entry;
+import java.util.Optional;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeMirror;
@@ -47,20 +46,28 @@ abstract class FactoryDescriptor {
};
abstract PackageAndClass name();
+
abstract TypeMirror extendingType();
+
abstract ImmutableSet<TypeMirror> implementingTypes();
+
abstract boolean publicType();
+
abstract ImmutableSet<FactoryMethodDescriptor> methodDescriptors();
+
abstract ImmutableSet<ImplementationMethodDescriptor> implementationMethodDescriptors();
+
abstract boolean allowSubclasses();
+
abstract ImmutableMap<Key, ProviderField> providers();
final AutoFactoryDeclaration declaration() {
- return Iterables.getFirst(methodDescriptors(), null).declaration();
+ // There is always at least one method descriptor.
+ return methodDescriptors().iterator().next().declaration();
}
private static class UniqueNameSet {
- private final Set<String> uniqueNames = new HashSet<String>();
+ private final Set<String> uniqueNames = new HashSet<>();
/**
* Generates a unique name using {@code base}. If {@code base} has not yet been added, it will
@@ -92,33 +99,37 @@ abstract class FactoryDescriptor {
}
ImmutableMap.Builder<Key, ProviderField> providersBuilder = ImmutableMap.builder();
UniqueNameSet uniqueNames = new UniqueNameSet();
- for (Entry<Key, Collection<Parameter>> entry :
- parametersForProviders.build().asMap().entrySet()) {
- Key key = entry.getKey();
- switch (entry.getValue().size()) {
- case 0:
- throw new AssertionError();
- case 1:
- Parameter parameter = Iterables.getOnlyElement(entry.getValue());
- providersBuilder.put(
- key,
- ProviderField.create(
- uniqueNames.getUniqueName(parameter.name() + "Provider"),
- key,
- parameter.nullable()));
- break;
- default:
- String providerName =
- uniqueNames.getUniqueName(
- invalidIdentifierCharacters.replaceFrom(key.toString(), '_') + "Provider");
- Optional<AnnotationMirror> nullable = Optional.absent();
- for (Parameter param : entry.getValue()) {
- nullable = nullable.or(param.nullable());
- }
- providersBuilder.put(key, ProviderField.create(providerName, key, nullable));
- break;
- }
- }
+ parametersForProviders
+ .build()
+ .asMap()
+ .forEach(
+ (key, parameters) -> {
+ switch (parameters.size()) {
+ case 0:
+ throw new AssertionError();
+ case 1:
+ Parameter parameter = Iterables.getOnlyElement(parameters);
+ providersBuilder.put(
+ key,
+ ProviderField.create(
+ uniqueNames.getUniqueName(parameter.name() + "Provider"),
+ key,
+ parameter.nullable()));
+ break;
+ default:
+ String providerName =
+ uniqueNames.getUniqueName(
+ invalidIdentifierCharacters.replaceFrom(key.toString(), '_')
+ + "Provider");
+ Optional<AnnotationMirror> nullable =
+ parameters.stream()
+ .map(Parameter::nullable)
+ .flatMap(Streams::stream)
+ .findFirst();
+ providersBuilder.put(key, ProviderField.create(providerName, key, nullable));
+ break;
+ }
+ });
ImmutableBiMap<FactoryMethodDescriptor, ImplementationMethodDescriptor>
duplicateMethodDescriptors =
@@ -129,8 +140,8 @@ abstract class FactoryDescriptor {
getDeduplicatedMethodDescriptors(methodDescriptors, duplicateMethodDescriptors);
ImmutableSet<ImplementationMethodDescriptor> deduplicatedImplementationMethodDescriptors =
- ImmutableSet.copyOf(
- Sets.difference(implementationMethodDescriptors, duplicateMethodDescriptors.values()));
+ Sets.difference(implementationMethodDescriptors, duplicateMethodDescriptors.values())
+ .immutableCopy();
return new AutoValue_FactoryDescriptor(
name,
@@ -191,12 +202,12 @@ abstract class FactoryDescriptor {
duplicateMethodDescriptors.get(methodDescriptor);
FactoryMethodDescriptor newMethodDescriptor =
- (duplicateMethodDescriptor != null)
- ? methodDescriptor
- .toBuilder()
+ (duplicateMethodDescriptor != null)
+ ? methodDescriptor.toBuilder()
.overridingMethod(true)
.publicMethod(duplicateMethodDescriptor.publicMethod())
.returnType(duplicateMethodDescriptor.returnType())
+ .exceptions(duplicateMethodDescriptor.exceptions())
.build()
: methodDescriptor;
deduplicatedMethodDescriptors.add(newMethodDescriptor);
@@ -213,8 +224,7 @@ abstract class FactoryDescriptor {
* in the same order.
*/
private static boolean areDuplicateMethodDescriptors(
- FactoryMethodDescriptor factory,
- ImplementationMethodDescriptor implementation) {
+ FactoryMethodDescriptor factory, ImplementationMethodDescriptor implementation) {
if (!factory.name().equals(implementation.name())) {
return false;
diff --git a/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptorGenerator.java b/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptorGenerator.java
index d2331f42..70a21ea2 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptorGenerator.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/FactoryDescriptorGenerator.java
@@ -18,6 +18,8 @@ package com.google.auto.factory.processor;
import static com.google.auto.common.MoreElements.isAnnotationPresent;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.partitioningBy;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.tools.Diagnostic.Kind.ERROR;
@@ -26,13 +28,11 @@ import com.google.auto.common.MoreElements;
import com.google.auto.factory.AutoFactory;
import com.google.auto.factory.Provided;
import com.google.common.base.Function;
-import com.google.common.base.Functions;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimaps;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import javax.annotation.processing.Messager;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
@@ -54,9 +54,7 @@ final class FactoryDescriptorGenerator {
private final AutoFactoryDeclaration.Factory declarationFactory;
FactoryDescriptorGenerator(
- Messager messager,
- Types types,
- AutoFactoryDeclaration.Factory declarationFactory) {
+ Messager messager, Types types, AutoFactoryDeclaration.Factory declarationFactory) {
this.messager = messager;
this.types = types;
this.declarationFactory = declarationFactory;
@@ -68,70 +66,75 @@ final class FactoryDescriptorGenerator {
if (!declaration.isPresent()) {
return ImmutableSet.of();
}
- return element.accept(new ElementKindVisitor6<ImmutableSet<FactoryMethodDescriptor>, Void>() {
- @Override
- protected ImmutableSet<FactoryMethodDescriptor> defaultAction(Element e, Void p) {
- throw new AssertionError("@AutoFactory applied to an impossible element");
- }
+ return element.accept(
+ new ElementKindVisitor6<ImmutableSet<FactoryMethodDescriptor>, Void>() {
+ @Override
+ protected ImmutableSet<FactoryMethodDescriptor> defaultAction(Element e, Void p) {
+ throw new AssertionError("@AutoFactory applied to an impossible element");
+ }
- @Override
- public ImmutableSet<FactoryMethodDescriptor> visitTypeAsClass(TypeElement type, Void p) {
- if (type.getModifiers().contains(ABSTRACT)) {
- // applied to an abstract factory
- messager.printMessage(ERROR,
- "Auto-factory doesn't support being applied to abstract classes.", type, mirror);
- return ImmutableSet.of();
- } else {
- // applied to the type to be created
- ImmutableSet<ExecutableElement> constructors = Elements2.getConstructors(type);
- if (constructors.isEmpty()) {
- return generateDescriptorForDefaultConstructor(declaration.get(), type);
- } else {
- return FluentIterable.from(constructors)
- .transform(new Function<ExecutableElement, FactoryMethodDescriptor>() {
- @Override public FactoryMethodDescriptor apply(ExecutableElement constructor) {
- return generateDescriptorForConstructor(declaration.get(), constructor);
- }
- })
- .toSet();
+ @Override
+ public ImmutableSet<FactoryMethodDescriptor> visitTypeAsClass(TypeElement type, Void p) {
+ if (type.getModifiers().contains(ABSTRACT)) {
+ // applied to an abstract factory
+ messager.printMessage(
+ ERROR,
+ "Auto-factory doesn't support being applied to abstract classes.",
+ type,
+ mirror);
+ return ImmutableSet.of();
+ } else {
+ // applied to the type to be created
+ ImmutableSet<ExecutableElement> constructors = Elements2.getConstructors(type);
+ if (constructors.isEmpty()) {
+ return generateDescriptorForDefaultConstructor(declaration.get(), type);
+ } else {
+ return FluentIterable.from(constructors)
+ .transform(
+ new Function<ExecutableElement, FactoryMethodDescriptor>() {
+ @Override
+ public FactoryMethodDescriptor apply(ExecutableElement constructor) {
+ return generateDescriptorForConstructor(declaration.get(), constructor);
+ }
+ })
+ .toSet();
+ }
+ }
}
- }
- }
- @Override
- public ImmutableSet<FactoryMethodDescriptor> visitTypeAsInterface(TypeElement type, Void p) {
- // applied to the factory interface
- messager.printMessage(ERROR,
- "Auto-factory doesn't support being applied to interfaces.", type, mirror);
- return ImmutableSet.of();
- }
+ @Override
+ public ImmutableSet<FactoryMethodDescriptor> visitTypeAsInterface(
+ TypeElement type, Void p) {
+ // applied to the factory interface
+ messager.printMessage(
+ ERROR, "Auto-factory doesn't support being applied to interfaces.", type, mirror);
+ return ImmutableSet.of();
+ }
- @Override
- public ImmutableSet<FactoryMethodDescriptor> visitExecutableAsConstructor(ExecutableElement e,
- Void p) {
- // applied to a constructor of a type to be created
- return ImmutableSet.of(generateDescriptorForConstructor(declaration.get(), e));
- }
- }, null);
+ @Override
+ public ImmutableSet<FactoryMethodDescriptor> visitExecutableAsConstructor(
+ ExecutableElement e, Void p) {
+ // applied to a constructor of a type to be created
+ return ImmutableSet.of(generateDescriptorForConstructor(declaration.get(), e));
+ }
+ },
+ null);
}
- FactoryMethodDescriptor generateDescriptorForConstructor(final AutoFactoryDeclaration declaration,
- ExecutableElement constructor) {
+ FactoryMethodDescriptor generateDescriptorForConstructor(
+ final AutoFactoryDeclaration declaration, ExecutableElement constructor) {
checkNotNull(constructor);
checkArgument(constructor.getKind() == ElementKind.CONSTRUCTOR);
TypeElement classElement = MoreElements.asType(constructor.getEnclosingElement());
- ImmutableListMultimap<Boolean, ? extends VariableElement> parameterMap =
- Multimaps.index(constructor.getParameters(), Functions.forPredicate(
- new Predicate<VariableElement>() {
- @Override
- public boolean apply(VariableElement parameter) {
- return isAnnotationPresent(parameter, Provided.class);
- }
- }));
+ Map<Boolean, List<VariableElement>> parameterMap =
+ constructor.getParameters().stream()
+ .collect(partitioningBy(parameter -> isAnnotationPresent(parameter, Provided.class)));
+ // The map returned by partitioningBy always has entries for both key values but our
+ // null-checker isn't yet smart enough to know that.
ImmutableSet<Parameter> providedParameters =
- Parameter.forParameterList(parameterMap.get(true), types);
+ Parameter.forParameterList(requireNonNull(parameterMap.get(true)), types);
ImmutableSet<Parameter> passedParameters =
- Parameter.forParameterList(parameterMap.get(false), types);
+ Parameter.forParameterList(requireNonNull(parameterMap.get(false)), types);
return FactoryMethodDescriptor.builder(declaration)
.name("create")
.returnType(classElement.asType())
@@ -140,6 +143,8 @@ final class FactoryDescriptorGenerator {
.passedParameters(passedParameters)
.creationParameters(Parameter.forParameterList(constructor.getParameters(), types))
.isVarArgs(constructor.isVarArgs())
+ .exceptions(constructor.getThrownTypes())
+ .overridingMethod(false)
.build();
}
@@ -150,9 +155,12 @@ final class FactoryDescriptorGenerator {
.name("create")
.returnType(type.asType())
.publicMethod(type.getModifiers().contains(PUBLIC))
- .passedParameters(ImmutableSet.<Parameter>of())
- .creationParameters(ImmutableSet.<Parameter>of())
- .providedParameters(ImmutableSet.<Parameter>of())
+ .providedParameters(ImmutableSet.of())
+ .passedParameters(ImmutableSet.of())
+ .creationParameters(ImmutableSet.of())
+ .isVarArgs(false)
+ .exceptions(ImmutableSet.of())
+ .overridingMethod(false)
.build());
}
}
diff --git a/factory/src/main/java/com/google/auto/factory/processor/FactoryMethodDescriptor.java b/factory/src/main/java/com/google/auto/factory/processor/FactoryMethodDescriptor.java
index 43e5097d..45259573 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/FactoryMethodDescriptor.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/FactoryMethodDescriptor.java
@@ -31,45 +31,65 @@ import javax.lang.model.type.TypeMirror;
@AutoValue
abstract class FactoryMethodDescriptor {
abstract AutoFactoryDeclaration declaration();
+
abstract String name();
+
abstract TypeMirror returnType();
+
abstract boolean publicMethod();
+
abstract boolean overridingMethod();
+
abstract ImmutableSet<Parameter> passedParameters();
+
abstract ImmutableSet<Parameter> providedParameters();
+
abstract ImmutableSet<Parameter> creationParameters();
- abstract Builder toBuilder();
+
abstract boolean isVarArgs();
+ abstract ImmutableSet<TypeMirror> exceptions();
+
+ abstract Builder toBuilder();
+
final PackageAndClass factoryName() {
return declaration().getFactoryName();
}
static Builder builder(AutoFactoryDeclaration declaration) {
- return new AutoValue_FactoryMethodDescriptor.Builder()
- .declaration(checkNotNull(declaration))
- .publicMethod(false)
- .overridingMethod(false)
- .isVarArgs(false);
+ return new AutoValue_FactoryMethodDescriptor.Builder().declaration(checkNotNull(declaration));
}
@AutoValue.Builder
abstract static class Builder {
abstract Builder declaration(AutoFactoryDeclaration declaration);
+
abstract Builder name(String name);
+
abstract Builder returnType(TypeMirror returnType);
+
abstract Builder publicMethod(boolean publicMethod);
+
abstract Builder overridingMethod(boolean overridingMethod);
+
abstract Builder passedParameters(Iterable<Parameter> passedParameters);
+
abstract Builder providedParameters(Iterable<Parameter> providedParameters);
+
abstract Builder creationParameters(Iterable<Parameter> creationParameters);
+
abstract Builder isVarArgs(boolean isVarargs);
+
+ abstract Builder exceptions(Iterable<? extends TypeMirror> exceptions);
+
abstract FactoryMethodDescriptor buildImpl();
FactoryMethodDescriptor build() {
FactoryMethodDescriptor descriptor = buildImpl();
- checkState(descriptor.creationParameters().equals(
- Sets.union(descriptor.passedParameters(), descriptor.providedParameters())));
+ checkState(
+ descriptor
+ .creationParameters()
+ .equals(Sets.union(descriptor.passedParameters(), descriptor.providedParameters())));
return descriptor;
}
}
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 53b99cb5..b7f9c3e4 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
@@ -19,19 +19,22 @@ import static com.google.auto.common.GeneratedAnnotationSpecs.generatedAnnotatio
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
import static com.squareup.javapoet.MethodSpec.methodBuilder;
import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;
import static javax.lang.model.element.Modifier.STATIC;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.collect.FluentIterable;
+import com.google.auto.common.AnnotationMirrors;
+import com.google.auto.common.AnnotationValues;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
+import com.google.common.collect.Streams;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
@@ -43,13 +46,19 @@ import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import java.io.IOException;
+import java.lang.annotation.Target;
import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.inject.Inject;
import javax.inject.Provider;
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.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
@@ -71,14 +80,10 @@ final class FactoryWriter {
this.factoriesBeingCreated = factoriesBeingCreated;
}
- private static final Joiner ARGUMENT_JOINER = Joiner.on(", ");
-
- void writeFactory(FactoryDescriptor descriptor)
- throws IOException {
+ void writeFactory(FactoryDescriptor descriptor) throws IOException {
String factoryName = descriptor.name().className();
TypeSpec.Builder factory =
- classBuilder(factoryName)
- .addOriginatingElement(descriptor.declaration().targetType());
+ classBuilder(factoryName).addOriginatingElement(descriptor.declaration().targetType());
generatedAnnotationSpec(
elements,
sourceVersion,
@@ -145,7 +150,7 @@ final class FactoryWriter {
ImmutableSet<TypeVariableName> factoryTypeVariables) {
for (FactoryMethodDescriptor methodDescriptor : descriptor.methodDescriptors()) {
MethodSpec.Builder method =
- MethodSpec.methodBuilder(methodDescriptor.name())
+ methodBuilder(methodDescriptor.name())
.addTypeVariables(getMethodTypeVariables(methodDescriptor, factoryTypeVariables))
.returns(TypeName.get(methodDescriptor.returnType()))
.varargs(methodDescriptor.isVarArgs());
@@ -155,6 +160,8 @@ final class FactoryWriter {
if (methodDescriptor.publicMethod()) {
method.addModifiers(PUBLIC);
}
+ method.addExceptions(
+ methodDescriptor.exceptions().stream().map(TypeName::get).collect(toList()));
CodeBlock.Builder args = CodeBlock.builder();
method.addParameters(parameters(methodDescriptor.passedParameters()));
Iterator<Parameter> parameters = methodDescriptor.creationParameters().iterator();
@@ -168,7 +175,7 @@ final class FactoryWriter {
checkNotNull = false;
}
} else {
- ProviderField provider = descriptor.providers().get(parameter.key());
+ ProviderField provider = requireNonNull(descriptor.providers().get(parameter.key()));
argument = CodeBlock.of(provider.name());
if (parameter.isProvider()) {
// Providers are checked for nullness in the Factory's constructor.
@@ -190,8 +197,7 @@ final class FactoryWriter {
}
}
- private void addImplementationMethods(
- TypeSpec.Builder factory, FactoryDescriptor descriptor) {
+ private void addImplementationMethods(TypeSpec.Builder factory, FactoryDescriptor descriptor) {
for (ImplementationMethodDescriptor methodDescriptor :
descriptor.implementationMethodDescriptors()) {
MethodSpec.Builder implementationMethod =
@@ -202,18 +208,12 @@ final class FactoryWriter {
if (methodDescriptor.publicMethod()) {
implementationMethod.addModifiers(PUBLIC);
}
+ implementationMethod.addExceptions(
+ methodDescriptor.exceptions().stream().map(TypeName::get).collect(toList()));
implementationMethod.addParameters(parameters(methodDescriptor.passedParameters()));
implementationMethod.addStatement(
"return create($L)",
- FluentIterable.from(methodDescriptor.passedParameters())
- .transform(
- new Function<Parameter, String>() {
- @Override
- public String apply(Parameter parameter) {
- return parameter.name();
- }
- })
- .join(ARGUMENT_JOINER));
+ methodDescriptor.passedParameters().stream().map(Parameter::name).collect(joining(", ")));
factory.addMethod(implementationMethod.build());
}
}
@@ -225,17 +225,43 @@ final class FactoryWriter {
private ImmutableList<ParameterSpec> parameters(Iterable<Parameter> parameters) {
ImmutableList.Builder<ParameterSpec> builder = ImmutableList.builder();
for (Parameter parameter : parameters) {
- ParameterSpec.Builder parameterBuilder =
- ParameterSpec.builder(resolveTypeName(parameter.type().get()), parameter.name());
- for (AnnotationMirror annotation :
- Iterables.concat(parameter.nullable().asSet(), parameter.key().qualifier().asSet())) {
- parameterBuilder.addAnnotation(AnnotationSpec.get(annotation));
- }
- builder.add(parameterBuilder.build());
+ TypeName type = resolveTypeName(parameter.type().get());
+ // Remove TYPE_USE annotations, since resolveTypeName will already have included those in
+ // the TypeName it returns.
+ List<AnnotationSpec> annotations =
+ Stream.of(parameter.nullable(), parameter.key().qualifier())
+ .flatMap(Streams::stream)
+ .filter(a -> !isTypeUseAnnotation(a))
+ .map(AnnotationSpec::get)
+ .collect(toList());
+ ParameterSpec parameterSpec =
+ ParameterSpec.builder(type, parameter.name()).addAnnotations(annotations).build();
+ builder.add(parameterSpec);
}
return builder.build();
}
+ private static boolean isTypeUseAnnotation(AnnotationMirror mirror) {
+ Element annotationElement = mirror.getAnnotationType().asElement();
+ // This is basically equivalent to:
+ // Target target = annotationElement.getAnnotation(Target.class);
+ // return target != null
+ // && Arrays.asList(annotationElement.getAnnotation(Target.class)).contains(TYPE_USE);
+ // but that might blow up if the annotation is being compiled at the same time and has an
+ // undefined identifier in its @Target values. The rigmarole below avoids that problem.
+ Optional<AnnotationMirror> maybeTargetMirror =
+ Mirrors.getAnnotationMirror(annotationElement, Target.class);
+ return maybeTargetMirror
+ .map(
+ targetMirror ->
+ AnnotationValues.getEnums(
+ AnnotationMirrors.getAnnotationValue(targetMirror, "value"))
+ .stream()
+ .map(VariableElement::getSimpleName)
+ .anyMatch(name -> name.contentEquals("TYPE_USE")))
+ .orElse(false);
+ }
+
private static void addCheckNotNullMethod(
TypeSpec.Builder factory, FactoryDescriptor descriptor) {
if (shouldGenerateCheckNotNull(descriptor)) {
@@ -290,17 +316,20 @@ final class FactoryWriter {
* {@code @AutoFactory class Foo} has a constructor parameter of type {@code BarFactory} and
* {@code @AutoFactory class Bar} has a constructor parameter of type {@code FooFactory}. We did
* in fact find instances of this in Google's source base.
+ *
+ * <p>If the type has type annotations then include those in the returned {@link TypeName}.
*/
private TypeName resolveTypeName(TypeMirror type) {
- if (type.getKind() != TypeKind.ERROR) {
- return TypeName.get(type);
- }
- ImmutableSet<PackageAndClass> factoryNames = factoriesBeingCreated.get(type.toString());
- if (factoryNames.size() == 1) {
- PackageAndClass packageAndClass = Iterables.getOnlyElement(factoryNames);
- return ClassName.get(packageAndClass.packageName(), packageAndClass.className());
+ TypeName typeName = TypeName.get(type);
+ if (type.getKind() == TypeKind.ERROR) {
+ ImmutableSet<PackageAndClass> factoryNames = factoriesBeingCreated.get(type.toString());
+ if (factoryNames.size() == 1) {
+ PackageAndClass packageAndClass = Iterables.getOnlyElement(factoryNames);
+ typeName = ClassName.get(packageAndClass.packageName(), packageAndClass.className());
+ }
}
- return TypeName.get(type);
+ return typeName.annotated(
+ type.getAnnotationMirrors().stream().map(AnnotationSpec::get).collect(toList()));
}
private static ImmutableSet<TypeVariableName> getFactoryTypeVariables(
diff --git a/factory/src/main/java/com/google/auto/factory/processor/ImplementationMethodDescriptor.java b/factory/src/main/java/com/google/auto/factory/processor/ImplementationMethodDescriptor.java
index 9ddc249f..b2705b7e 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/ImplementationMethodDescriptor.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/ImplementationMethodDescriptor.java
@@ -22,21 +22,25 @@ import javax.lang.model.type.TypeMirror;
@AutoValue
abstract class ImplementationMethodDescriptor {
abstract String name();
+
abstract TypeMirror returnType();
+
abstract boolean publicMethod();
+
abstract ImmutableSet<Parameter> passedParameters();
+
abstract boolean isVarArgs();
+ abstract ImmutableSet<TypeMirror> exceptions();
+
static Builder builder() {
- return new AutoValue_ImplementationMethodDescriptor.Builder()
- .publicMethod(true)
- .isVarArgs(false);
+ return new AutoValue_ImplementationMethodDescriptor.Builder();
}
@AutoValue.Builder
- static abstract class Builder {
+ abstract static class Builder {
abstract Builder name(String name);
-
+
abstract Builder returnType(TypeMirror returnTypeElement);
abstract Builder publicMethod(boolean publicMethod);
@@ -49,6 +53,8 @@ abstract class ImplementationMethodDescriptor {
abstract Builder isVarArgs(boolean isVarargs);
+ abstract Builder exceptions(Iterable<? extends TypeMirror> exceptions);
+
abstract ImplementationMethodDescriptor build();
}
}
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 04bd4f37..728149eb 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
@@ -24,9 +24,8 @@ import com.google.auto.common.AnnotationMirrors;
import com.google.auto.common.MoreTypes;
import com.google.auto.value.AutoValue;
import com.google.common.base.Equivalence;
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
+import java.util.Optional;
import javax.inject.Qualifier;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.TypeMirror;
@@ -65,17 +64,15 @@ abstract class Key {
* <tr><td>{@code int} <td>{@code Integer}
* </table>
*/
- static Key create(
- TypeMirror type, Iterable<? extends AnnotationMirror> annotations, Types types) {
- ImmutableSet.Builder<AnnotationMirror> qualifiers = ImmutableSet.builder();
- for (AnnotationMirror annotation : annotations) {
- if (isAnnotationPresent(annotation.getAnnotationType().asElement(), Qualifier.class)) {
- qualifiers.add(annotation);
- }
- }
-
+ static Key create(TypeMirror type, Collection<AnnotationMirror> annotations, Types types) {
// TODO(gak): check for only one qualifier rather than using the first
- Optional<AnnotationMirror> qualifier = FluentIterable.from(qualifiers.build()).first();
+ Optional<AnnotationMirror> qualifier =
+ annotations.stream()
+ .filter(
+ annotation ->
+ isAnnotationPresent(
+ annotation.getAnnotationType().asElement(), Qualifier.class))
+ .findFirst();
TypeMirror keyType =
isProvider(type)
@@ -97,7 +94,7 @@ abstract class Key {
}
@Override
- public String toString() {
+ public final String toString() {
String typeQualifiedName = MoreTypes.asTypeElement(type().get()).toString();
return qualifier().isPresent()
? qualifier().get() + "/" + typeQualifiedName
diff --git a/factory/src/main/java/com/google/auto/factory/processor/Mirrors.java b/factory/src/main/java/com/google/auto/factory/processor/Mirrors.java
index c5b7d8bf..313fc9ee 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/Mirrors.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/Mirrors.java
@@ -17,11 +17,11 @@ package com.google.auto.factory.processor;
import com.google.auto.common.MoreTypes;
import com.google.common.base.Equivalence;
-import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Optional;
import javax.inject.Provider;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
@@ -34,20 +34,23 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleElementVisitor6;
final class Mirrors {
- private Mirrors() { }
+ private Mirrors() {}
static Name getQualifiedName(DeclaredType type) {
- return type.asElement().accept(new SimpleElementVisitor6<Name, Void>() {
- @Override
- protected Name defaultAction(Element e, Void p) {
- throw new AssertionError("DeclaredTypes should be TypeElements");
- }
+ return type.asElement()
+ .accept(
+ new SimpleElementVisitor6<Name, Void>() {
+ @Override
+ protected Name defaultAction(Element e, Void p) {
+ throw new AssertionError("DeclaredTypes should be TypeElements");
+ }
- @Override
- public Name visitType(TypeElement e, Void p) {
- return e.getQualifiedName();
- }
- }, null);
+ @Override
+ public Name visitType(TypeElement e, Void p) {
+ return e.getQualifiedName();
+ }
+ },
+ null);
}
/** {@code true} if {@code type} is a {@link Provider}. */
@@ -62,8 +65,8 @@ final class Mirrors {
static ImmutableMap<String, AnnotationValue> simplifyAnnotationValueMap(
Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValueMap) {
ImmutableMap.Builder<String, AnnotationValue> builder = ImmutableMap.builder();
- for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry
- : annotationValueMap.entrySet()) {
+ for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
+ annotationValueMap.entrySet()) {
builder.put(entry.getKey().getSimpleName().toString(), entry.getValue());
}
return builder.build();
@@ -73,15 +76,13 @@ final class Mirrors {
* Get the {@link AnnotationMirror} for the type {@code annotationType} present on the given
* {@link Element} if it exists.
*/
- static Optional<AnnotationMirror> getAnnotationMirror(Element element,
- Class<? extends Annotation> annotationType) {
+ static Optional<AnnotationMirror> getAnnotationMirror(
+ Element element, Class<? extends Annotation> annotationType) {
String annotationName = annotationType.getName();
- for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
- if (getQualifiedName(annotationMirror.getAnnotationType()).contentEquals(annotationName)) {
- return Optional.of(annotationMirror);
- }
- }
- return Optional.absent();
+ return element.getAnnotationMirrors().stream()
+ .filter(a -> getQualifiedName(a.getAnnotationType()).contentEquals(annotationName))
+ .<AnnotationMirror>map(x -> x) // get rid of wildcard <? extends AnnotationMirror>
+ .findFirst();
}
/**
@@ -91,9 +92,7 @@ final class Mirrors {
// TODO(ronshapiro): this is used in AutoFactory and Dagger, consider moving it into auto-common.
static <T> Optional<Equivalence.Wrapper<T>> wrapOptionalInEquivalence(
Equivalence<T> equivalence, Optional<T> optional) {
- return optional.isPresent()
- ? Optional.of(equivalence.wrap(optional.get()))
- : Optional.<Equivalence.Wrapper<T>>absent();
+ return optional.map(equivalence::wrap);
}
/**
@@ -102,8 +101,6 @@ final class Mirrors {
*/
static <T> Optional<T> unwrapOptionalEquivalence(
Optional<Equivalence.Wrapper<T>> wrappedOptional) {
- return wrappedOptional.isPresent()
- ? Optional.of(wrappedOptional.get().get())
- : Optional.<T>absent();
+ return wrappedOptional.map(Equivalence.Wrapper::get);
}
}
diff --git a/factory/src/main/java/com/google/auto/factory/processor/Parameter.java b/factory/src/main/java/com/google/auto/factory/processor/Parameter.java
index 781225a2..c5059ece 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/Parameter.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/Parameter.java
@@ -18,19 +18,20 @@ package com.google.auto.factory.processor;
import static com.google.auto.factory.processor.Mirrors.unwrapOptionalEquivalence;
import static com.google.auto.factory.processor.Mirrors.wrapOptionalInEquivalence;
import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.stream.Collectors.toList;
import com.google.auto.common.AnnotationMirrors;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.auto.value.AutoValue;
import com.google.common.base.Equivalence;
-import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Stream;
import javax.inject.Provider;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
@@ -63,6 +64,7 @@ abstract class Parameter {
abstract String name();
abstract Key key();
+
abstract Optional<Equivalence.Wrapper<AnnotationMirror>> nullableWrapper();
Optional<AnnotationMirror> nullable() {
@@ -71,15 +73,12 @@ abstract class Parameter {
private static Parameter forVariableElement(
VariableElement variable, TypeMirror type, Types types) {
- Optional<AnnotationMirror> nullable = Optional.absent();
- Iterable<? extends AnnotationMirror> annotations =
- Iterables.concat(variable.getAnnotationMirrors(), type.getAnnotationMirrors());
- for (AnnotationMirror annotation : annotations) {
- if (isNullable(annotation)) {
- nullable = Optional.of(annotation);
- break;
- }
- }
+ List<AnnotationMirror> annotations =
+ Stream.of(variable.getAnnotationMirrors(), type.getAnnotationMirrors())
+ .flatMap(List::stream)
+ .collect(toList());
+ Optional<AnnotationMirror> nullable =
+ annotations.stream().filter(Parameter::isNullable).findFirst();
Key key = Key.create(type, annotations, types);
return new AutoValue_Parameter(
@@ -108,7 +107,7 @@ abstract class Parameter {
Set<String> names = Sets.newHashSetWithExpectedSize(variables.size());
for (int i = 0; i < variables.size(); i++) {
Parameter parameter = forVariableElement(variables.get(i), variableTypes.get(i), types);
- checkArgument(names.add(parameter.name()));
+ checkArgument(names.add(parameter.name()), "Duplicate parameter name: %s", parameter.name());
builder.add(parameter);
}
ImmutableSet<Parameter> parameters = builder.build();
diff --git a/factory/src/main/java/com/google/auto/factory/processor/ProvidedChecker.java b/factory/src/main/java/com/google/auto/factory/processor/ProvidedChecker.java
index fe4c1fd2..bd88f837 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/ProvidedChecker.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/ProvidedChecker.java
@@ -26,6 +26,7 @@ import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementKindVisitor6;
+import org.checkerframework.checker.nullness.qual.Nullable;
final class ProvidedChecker {
private final Messager messager;
@@ -35,41 +36,54 @@ final class ProvidedChecker {
}
void checkProvidedParameter(Element element) {
- checkArgument(isAnnotationPresent(element, Provided.class), "%s not annoated with @Provided",
- element);
- element.accept(new ElementKindVisitor6<Void, Void>() {
- @Override
- protected Void defaultAction(Element e, Void p) {
- throw new AssertionError("Provided can only be applied to parameters");
- }
-
- @Override
- public Void visitVariableAsParameter(final VariableElement providedParameter, Void p) {
- providedParameter.getEnclosingElement().accept(new ElementKindVisitor6<Void, Void>() {
+ checkArgument(
+ isAnnotationPresent(element, Provided.class), "%s not annoated with @Provided", element);
+ element.accept(
+ new ElementKindVisitor6<@Nullable Void, @Nullable Void>() {
@Override
- protected Void defaultAction(Element e, Void p) {
- raiseError(providedParameter, "@%s may only be applied to constructor parameters");
- return null;
+ protected @Nullable Void defaultAction(Element e, @Nullable Void p) {
+ throw new AssertionError("Provided can only be applied to parameters");
}
@Override
- public Void visitExecutableAsConstructor(ExecutableElement constructor, Void p) {
- if (!(annotatedWithAutoFactory(constructor)
- || annotatedWithAutoFactory(constructor.getEnclosingElement()))) {
- raiseError(providedParameter,
- "@%s may only be applied to constructors requesting an auto-factory");
- }
+ public @Nullable Void visitVariableAsParameter(
+ VariableElement providedParameter, @Nullable Void p) {
+ providedParameter
+ .getEnclosingElement()
+ .accept(
+ new ElementKindVisitor6<@Nullable Void, @Nullable Void>() {
+ @Override
+ protected @Nullable Void defaultAction(Element e, @Nullable Void p) {
+ raiseError(
+ providedParameter, "@%s may only be applied to constructor parameters");
+ return null;
+ }
+
+ @Override
+ public @Nullable Void visitExecutableAsConstructor(
+ ExecutableElement constructor, @Nullable Void p) {
+ if (!(annotatedWithAutoFactory(constructor)
+ || annotatedWithAutoFactory(constructor.getEnclosingElement()))) {
+ raiseError(
+ providedParameter,
+ "@%s may only be applied to constructors requesting an auto-factory");
+ }
+ return null;
+ }
+ },
+ p);
return null;
}
- }, p);
- return null;
- }
- }, null);
+ },
+ null);
}
private void raiseError(VariableElement providedParameter, String messageFormat) {
- messager.printMessage(ERROR, String.format(messageFormat, Provided.class.getSimpleName()),
- providedParameter, Mirrors.getAnnotationMirror(providedParameter, Provided.class).get());
+ messager.printMessage(
+ ERROR,
+ String.format(messageFormat, Provided.class.getSimpleName()),
+ providedParameter,
+ Mirrors.getAnnotationMirror(providedParameter, Provided.class).get());
}
private static boolean annotatedWithAutoFactory(Element e) {
diff --git a/factory/src/main/java/com/google/auto/factory/processor/ProviderField.java b/factory/src/main/java/com/google/auto/factory/processor/ProviderField.java
index 855c1feb..99847ec0 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/ProviderField.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/ProviderField.java
@@ -21,13 +21,15 @@ import static com.google.auto.factory.processor.Mirrors.wrapOptionalInEquivalenc
import com.google.auto.common.AnnotationMirrors;
import com.google.auto.value.AutoValue;
import com.google.common.base.Equivalence;
-import com.google.common.base.Optional;
+import java.util.Optional;
import javax.lang.model.element.AnnotationMirror;
@AutoValue
abstract class ProviderField {
abstract String name();
+
abstract Key key();
+
abstract Optional<Equivalence.Wrapper<AnnotationMirror>> nullableWrapper();
Optional<AnnotationMirror> nullable() {
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 1f894732..4bd546e8 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
@@ -38,8 +38,8 @@ final class TypeVariables {
return type.accept(ReferencedTypeVariables.INSTANCE, new HashSet<>());
}
- private static final class ReferencedTypeVariables extends
- SimpleTypeVisitor8<ImmutableSet<TypeVariable>, Set<Element>> {
+ private static final class ReferencedTypeVariables
+ extends SimpleTypeVisitor8<ImmutableSet<TypeVariable>, Set<Element>> {
private static final ReferencedTypeVariables INSTANCE = new ReferencedTypeVariables();
@@ -53,8 +53,7 @@ final class TypeVariables {
}
@Override
- public ImmutableSet<TypeVariable> visitDeclared(
- DeclaredType t, Set<Element> visited) {
+ public ImmutableSet<TypeVariable> visitDeclared(DeclaredType t, Set<Element> visited) {
if (!visited.add(t.asElement())) {
return ImmutableSet.of();
}
@@ -66,8 +65,7 @@ final class TypeVariables {
}
@Override
- public ImmutableSet<TypeVariable> visitTypeVariable(
- TypeVariable t, Set<Element> visited) {
+ public ImmutableSet<TypeVariable> visitTypeVariable(TypeVariable t, Set<Element> visited) {
if (!visited.add(t.asElement())) {
return ImmutableSet.of();
}
@@ -79,8 +77,7 @@ final class TypeVariables {
}
@Override
- public ImmutableSet<TypeVariable> visitUnion(
- UnionType t, Set<Element> visited) {
+ 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, visited));
@@ -89,8 +86,7 @@ final class TypeVariables {
}
@Override
- public ImmutableSet<TypeVariable> visitIntersection(
- IntersectionType t, Set<Element> visited) {
+ 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, visited));
@@ -99,8 +95,7 @@ final class TypeVariables {
}
@Override
- public ImmutableSet<TypeVariable> visitWildcard(
- WildcardType t, Set<Element> visited) {
+ public ImmutableSet<TypeVariable> visitWildcard(WildcardType t, Set<Element> visited) {
ImmutableSet.Builder<TypeVariable> typeVariables = ImmutableSet.builder();
TypeMirror extendsBound = t.getExtendsBound();
if (extendsBound != null) {
diff --git a/factory/src/main/java/com/google/auto/factory/processor/package-info.java b/factory/src/main/java/com/google/auto/factory/processor/package-info.java
index 7339020a..4a7c4b10 100644
--- a/factory/src/main/java/com/google/auto/factory/processor/package-info.java
+++ b/factory/src/main/java/com/google/auto/factory/processor/package-info.java
@@ -15,4 +15,5 @@
* This package contains the annotation processor that implements the
* {@link com.google.auto.factory.AutoFactory} API.
*/
-package com.google.auto.factory.processor; \ No newline at end of file
+package com.google.auto.factory.processor;
+