diff options
Diffstat (limited to 'value/src/main/java/com/google')
11 files changed, 216 insertions, 128 deletions
diff --git a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java index db2f2212..0ca46bde 100644 --- a/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java +++ b/value/src/main/java/com/google/auto/value/extension/memoized/processor/MemoizeExtension.java @@ -100,8 +100,11 @@ public final class MemoizeExtension extends AutoValueExtension { private static final String AUTO_VALUE_NAME = AUTO_VALUE_PACKAGE_NAME + "AutoValue"; private static final String COPY_ANNOTATIONS_NAME = AUTO_VALUE_NAME + ".CopyAnnotations"; + // Maven is configured to shade (rewrite) com.google packages to prevent dependency conflicts. + // Split up the package here with a call to concat to prevent Maven from finding and rewriting it, + // so that this will be able to find the LazyInit annotation if it's on the classpath. private static final ClassName LAZY_INIT = - ClassName.get("com.google.errorprone.annotations.concurrent", "LazyInit"); + ClassName.get("com".concat(".google.errorprone.annotations.concurrent"), "LazyInit"); private static final AnnotationSpec SUPPRESS_WARNINGS = AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "Immutable").build(); diff --git a/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java index d05ed43c..d73c1c29 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java @@ -72,7 +72,9 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { void processType(TypeElement autoOneOfType) { if (autoOneOfType.getKind() != ElementKind.CLASS) { errorReporter() - .abortWithError(autoOneOfType, "@" + AUTO_ONE_OF_NAME + " only applies to classes"); + .abortWithError( + autoOneOfType, + "[AutoOneOfNotClass] @" + AUTO_ONE_OF_NAME + " only applies to classes"); } checkModifiersIfNested(autoOneOfType); DeclaredType kindMirror = mirrorForKindType(autoOneOfType); @@ -129,7 +131,7 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { errorReporter() .abortWithError( autoOneOfType, - "annotation processor for @AutoOneOf was invoked with a type" + "[AutoOneOfCompilerBug] annotation processor for @AutoOneOf was invoked with a type" + " that does not have that annotation; this is probably a compiler bug"); } AnnotationValue kindValue = @@ -184,7 +186,8 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportError( kindElement, - "Enum has no constant with name corresponding to property '%s'", + "[AutoOneOfNoEnumConstant] Enum has no constant with name corresponding to" + + " property '%s'", property); } }); @@ -195,7 +198,8 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportError( constant, - "Name of enum constant '%s' does not correspond to any property name", + "[AutoOneOfBadEnumConstant] Name of enum constant '%s' does not correspond to" + + " any property name", constant.getSimpleName()); } }); @@ -221,7 +225,7 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportError( autoOneOfType, - "%s must have a no-arg abstract method returning %s", + "[AutoOneOfNoKindGetter] %s must have a no-arg abstract method returning %s", autoOneOfType, kindMirror); break; @@ -230,7 +234,10 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { default: for (ExecutableElement getter : kindGetters) { errorReporter() - .reportError(getter, "More than one abstract method returns %s", kindMirror); + .reportError( + getter, + "[AutoOneOfTwoKindGetters] More than one abstract method returns %s", + kindMirror); } } throw new AbortProcessingException(); @@ -254,7 +261,8 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { // implement this alien method. errorReporter() .reportWarning( - method, "Abstract methods in @AutoOneOf classes must have no parameters"); + method, + "[AutoOneOfParams] Abstract methods in @AutoOneOf classes must have no parameters"); } } errorReporter().abortIfAnyError(); @@ -278,7 +286,9 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor { @Override Optional<String> nullableAnnotationForMethod(ExecutableElement propertyMethod) { if (nullableAnnotationFor(propertyMethod, propertyMethod.getReturnType()).isPresent()) { - errorReporter().reportError(propertyMethod, "@AutoOneOf properties cannot be @Nullable"); + errorReporter() + .reportError( + propertyMethod, "[AutoOneOfNullable] @AutoOneOf properties cannot be @Nullable"); } return Optional.empty(); } diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java index 4214c128..36a82bd4 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java @@ -71,7 +71,6 @@ import javax.lang.model.element.QualifiedNameable; import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -301,7 +300,8 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { for (TypeElement type : deferredTypes) { errorReporter.reportError( type, - "Did not generate @%s class for %s because it references undefined types", + "[AutoValueUndefined] Did not generate @%s class for %s because it references" + + " undefined types", simpleAnnotationName, type.getQualifiedName()); } @@ -331,7 +331,10 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { } catch (RuntimeException e) { String trace = Throwables.getStackTraceAsString(e); errorReporter.reportError( - type, "@%s processor threw an exception: %s", simpleAnnotationName, trace); + type, + "[AutoValueException] @%s processor threw an exception: %s", + simpleAnnotationName, + trace); throw e; } } @@ -378,8 +381,9 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { ImmutableSet.Builder<Property> props = ImmutableSet.builder(); propertyMethodsAndTypes.forEach( (propertyMethod, returnType) -> { - String propertyType = TypeEncoder.encodeWithAnnotations( - returnType, getExcludedAnnotationTypes(propertyMethod)); + String propertyType = + TypeEncoder.encodeWithAnnotations( + returnType, getExcludedAnnotationTypes(propertyMethod)); String propertyName = methodToPropertyName.get(propertyMethod); String identifier = methodToIdentifier.get(propertyMethod); ImmutableList<String> fieldAnnotations = @@ -399,7 +403,9 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { nullableAnnotation); props.add(p); if (p.isNullable() && returnType.getKind().isPrimitive()) { - errorReporter().reportError(propertyMethod, "Primitive types cannot be @Nullable"); + errorReporter() + .reportError( + propertyMethod, "[AutoValueNullPrimitive] Primitive types cannot be @Nullable"); } }); return props.build(); @@ -517,7 +523,10 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { // reportedDups prevents us from reporting more than one error for the same method. for (ExecutableElement context : contexts) { errorReporter.reportError( - context, "More than one @%s property called %s", simpleAnnotationName, name); + context, + "[AutoValueDupProperty] More than one @%s property called %s", + simpleAnnotationName, + name); } } } @@ -622,16 +631,18 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { if (enclosingKind.isClass() || enclosingKind.isInterface()) { if (type.getModifiers().contains(Modifier.PRIVATE)) { errorReporter.abortWithError( - type, "@%s class must not be private", simpleAnnotationName); + type, "[AutoValuePrivate] @%s class must not be private", simpleAnnotationName); } else if (Visibility.effectiveVisibilityOfElement(type).equals(Visibility.PRIVATE)) { // The previous case, where the class itself is private, is much commoner so it deserves // its own error message, even though it would be caught by the test here too. errorReporter.abortWithError( - type, "@%s class must not be nested in a private class", simpleAnnotationName); + type, + "[AutoValueInPrivate] @%s class must not be nested in a private class", + simpleAnnotationName); } if (!type.getModifiers().contains(Modifier.STATIC)) { errorReporter.abortWithError( - type, "Nested @%s class must be static", simpleAnnotationName); + type, "[AutoValueInner] Nested @%s class must be static", simpleAnnotationName); } } // In principle type.getEnclosingElement() could be an ExecutableElement (for a class @@ -766,13 +777,14 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { final void checkReturnType(TypeElement autoValueClass, ExecutableElement getter) { TypeMirror type = getter.getReturnType(); if (type.getKind() == TypeKind.ARRAY) { - TypeMirror componentType = ((ArrayType) type).getComponentType(); - if (componentType.getKind().isPrimitive()) { + TypeMirror componentType = MoreTypes.asArray(type).getComponentType(); + if (componentType.getKind().isPrimitive()) { warnAboutPrimitiveArrays(autoValueClass, getter); } else { errorReporter.reportError( getter, - "An @%s class cannot define an array-valued property unless it is a primitive array", + "[AutoValueArray] An @%s class cannot define an array-valued property unless it is a" + + " primitive array", simpleAnnotationName); } } @@ -799,10 +811,11 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { String context = sameClass ? "" : (" Method: " + getter.getEnclosingElement() + "." + getter); errorReporter.reportWarning( element, - "An @%s property that is a primitive array returns the original array, which can" - + " therefore be modified by the caller. If this is OK, you can suppress this warning" - + " with @SuppressWarnings(\"mutable\"). Otherwise, you should replace the property" - + " with an immutable type, perhaps a simple wrapper around the original array.%s", + "[AutoValueMutable] An @%s property that is a primitive array returns the original" + + " array, which can therefore be modified by the caller. If this is OK, you can" + + " suppress this warning with @SuppressWarnings(\"mutable\"). Otherwise, you should" + + " replace the property with an immutable type, perhaps a simple wrapper around the" + + " original array.%s", simpleAnnotationName, context); } @@ -815,8 +828,8 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { private static class ContainsMutableVisitor extends SimpleAnnotationValueVisitor8<Boolean, Void> { @Override public Boolean visitArray(List<? extends AnnotationValue> list, Void p) { - return list.stream().map(av -> av.getValue()).anyMatch("mutable"::equals); - } + return list.stream().map(AnnotationValue::getValue).anyMatch("mutable"::equals); + } } /** @@ -1102,7 +1115,10 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor { // error later because user code will have a reference to the code we were supposed to // generate (new AutoValue_Foo() or whatever) and that reference will be undefined. errorReporter.reportWarning( - originatingType, "Could not write generated class %s: %s", className, e); + originatingType, + "[AutoValueCouldNotWrite] Could not write generated class %s: %s", + className, + e); } } } diff --git a/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java index f3b396ca..aafffd7c 100644 --- a/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java +++ b/value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java @@ -121,8 +121,8 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportWarning( null, - "An exception occurred while looking for AutoValue extensions." - + " No extensions will function.%s\n%s", + "[AutoValueExtensionsException] An exception occurred while looking for AutoValue" + + " extensions. No extensions will function.%s\n%s", explain, Throwables.getStackTraceAsString(e)); extensions = ImmutableList.of(); @@ -170,19 +170,22 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { errorReporter() .abortWithError( type, - "annotation processor for @AutoValue was invoked with a type" + "[AutoValueCompilerBug] annotation processor for @AutoValue was invoked with a type" + " that does not have that annotation; this is probably a compiler bug"); } if (type.getKind() != ElementKind.CLASS) { - errorReporter().abortWithError(type, "@AutoValue only applies to classes"); + errorReporter() + .abortWithError(type, "[AutoValueNotClass] @AutoValue only applies to classes"); } if (ancestorIsAutoValue(type)) { - errorReporter().abortWithError(type, "One @AutoValue class may not extend another"); + errorReporter() + .abortWithError(type, "[AutoValueExtend] One @AutoValue class may not extend another"); } if (implementsAnnotation(type)) { errorReporter() .abortWithError( - type, "@AutoValue may not be used to implement an annotation" + type, + "[AutoValueImplAnnotation] @AutoValue may not be used to implement an annotation" + " interface; try using @AutoAnnotation instead"); } checkModifiersIfNested(type); @@ -333,7 +336,8 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportError( type, - "More than one extension wants to generate the final class: %s", + "[AutoValueMultiFinal] More than one extension wants to generate the final class:" + + " %s", finalExtensions.stream().map(this::extensionName).collect(joining(", "))); break; } @@ -355,7 +359,8 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportError( type, - "Extension %s wants to consume a property that does not exist: %s", + "[AutoValueConsumeNonexist] Extension %s wants to consume a property that does" + + " not exist: %s", extensionName(extension), consumedProperty); } else { @@ -367,8 +372,8 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportError( type, - "Extension %s wants to consume a method that is not one of the abstract methods" - + " in this class: %s", + "[AutoValueConsumeNotAbstract] Extension %s wants to consume a method that is" + + " not one of the abstract methods in this class: %s", extensionName(extension), consumedMethod); } else { @@ -379,8 +384,8 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { errorReporter() .reportError( repeat, - "Extension %s wants to consume a method that was already consumed by another" - + " extension", + "[AutoValueMultiConsume] Extension %s wants to consume a method that was already" + + " consumed by another extension", extensionName(extension)); } consumed.addAll(consumedHere); @@ -404,10 +409,12 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor { // another, and therefore leaves us with both an abstract method and the subclass method // that overrides it. This shows up in AutoValueTest.LukesBase for example. String extensionMessage = extensionsPresent ? ", and no extension consumed it" : ""; - errorReporter().reportWarning( - method, - "Abstract method is neither a property getter nor a Builder converter%s", - extensionMessage); + errorReporter() + .reportWarning( + method, + "[AutoValueBuilderWhat] Abstract method is neither a property getter nor a Builder" + + " converter%s", + extensionMessage); } } errorReporter().abortIfAnyError(); diff --git a/value/src/main/java/com/google/auto/value/processor/BuilderMethodClassifier.java b/value/src/main/java/com/google/auto/value/processor/BuilderMethodClassifier.java index 724a3225..81751e30 100644 --- a/value/src/main/java/com/google/auto/value/processor/BuilderMethodClassifier.java +++ b/value/src/main/java/com/google/auto/value/processor/BuilderMethodClassifier.java @@ -20,6 +20,7 @@ import static com.google.common.collect.Sets.difference; import com.google.auto.common.MoreElements; import com.google.auto.common.MoreTypes; +import com.google.auto.value.processor.BuilderSpec.Copier; import com.google.auto.value.processor.BuilderSpec.PropertySetter; import com.google.auto.value.processor.PropertyBuilderClassifier.PropertyBuilder; import com.google.common.base.Equivalence; @@ -197,7 +198,7 @@ class BuilderMethodClassifier { } else { errorReporter.reportError( propertyNameToUnprefixedSetters.values().iterator().next().getSetter(), - "If any setter methods use the setFoo convention then all must"); + "[AutoValueSetNotSet] If any setter methods use the setFoo convention then all must"); return false; } getterToPropertyName.forEach( @@ -219,10 +220,10 @@ class BuilderMethodClassifier { if (needToMakeBarBuilder && !canMakeBarBuilder) { errorReporter.reportError( propertyBuilder.getPropertyBuilderMethod(), - "Property builder method returns %1$s but there is no way to make that type" - + " from %2$s: %2$s does not have a non-static toBuilder() method that" - + " returns %1$s, and %1$s does not have a method addAll or" - + " putAll that accepts an argument of type %2$s", + "[AutoValueCantMakeBuilder] Property builder method returns %1$s but there is no" + + " way to make that type from %2$s: %2$s does not have a non-static" + + " toBuilder() method that returns %1$s, and %1$s does not have a method" + + " addAll or putAll that accepts an argument of type %2$s", propertyBuilder.getBuilderTypeMirror(), propertyType); } @@ -231,8 +232,13 @@ class BuilderMethodClassifier { String setterName = settersPrefixed ? prefixWithSet(property) : property; errorReporter.reportError( builderType, - "Expected a method with this signature: %s%s %s(%s), or a %sBuilder() method", - builderType, typeParamsString(), setterName, propertyType, property); + "[AutoValueBuilderMissingMethod] Expected a method with this signature: %s%s" + + " %s(%s), or a %sBuilder() method", + builderType, + typeParamsString(), + setterName, + propertyType, + property); } }); return errorReporter.errorCount() == startErrorCount; @@ -248,7 +254,8 @@ class BuilderMethodClassifier { classifyMethodOneArg(method); break; default: - errorReporter.reportError(method, "Builder methods must have 0 or 1 parameters"); + errorReporter.reportError( + method, "[AutoValueBuilderArgs] Builder methods must have 0 or 1 parameters"); } } @@ -296,10 +303,11 @@ class BuilderMethodClassifier { } else { errorReporter.reportError( method, - "Method without arguments should be a build method returning %1$s%2$s," - + " or a getter method with the same name and type as a getter method of %1$s," - + " or fooBuilder() where foo() or getFoo() is a getter method of %1$s", - autoValueClass, typeParamsString()); + "[AutoValueBuilderNoArg] Method without arguments should be a build method returning" + + " %1$s%2$s, or a getter method with the same name and type as a getter method of" + + " %1$s, or fooBuilder() where foo() or getFoo() is a getter method of %1$s", + autoValueClass, + typeParamsString()); } } @@ -334,9 +342,11 @@ class BuilderMethodClassifier { } errorReporter.reportError( builderGetter, - "Method matches a property of %1$s but has return type %2$s instead of %3$s " - + "or an Optional wrapping of %3$s", - autoValueClass, builderGetterType, originalGetterType); + "[AutoValueBuilderReturnType] Method matches a property of %1$s but has return type %2$s" + + " instead of %3$s or an Optional wrapping of %3$s", + autoValueClass, + builderGetterType, + originalGetterType); } /** @@ -372,11 +382,13 @@ class BuilderMethodClassifier { // The second disjunct isn't needed but convinces control-flow checkers that // propertyNameToSetters can't be null when we call put on it below. errorReporter.reportError( - method, "Method does not correspond to a property of %s", autoValueClass); + method, + "[AutoValueBuilderWhatProp] Method does not correspond to a property of %s", + autoValueClass); checkForFailedJavaBean(method); return; } - Optional<Function<String, String>> function = getSetterFunction(valueGetter, method); + Optional<Copier> function = getSetterFunction(valueGetter, method); if (function.isPresent()) { DeclaredType builderTypeMirror = MoreTypes.asDeclared(builderType.asType()); ExecutableType methodMirror = @@ -419,7 +431,7 @@ class BuilderMethodClassifier { * using a method like {@code ImmutableList.copyOf} or {@code Optional.of}, when the returned * function will be something like {@code s -> "Optional.of(" + s + ")"}. */ - private Optional<Function<String, String>> getSetterFunction( + private Optional<Copier> getSetterFunction( ExecutableElement valueGetter, ExecutableElement setter) { VariableElement parameterElement = Iterables.getOnlyElement(setter.getParameters()); boolean nullableParameter = @@ -440,12 +452,14 @@ class BuilderMethodClassifier { if (!nullableProperty) { errorReporter.reportError( setter, - "Parameter of setter method is @Nullable but property method %s.%s() is not", - autoValueClass, valueGetter.getSimpleName()); + "[AutoValueNullNotNull] Parameter of setter method is @Nullable but property method" + + " %s.%s() is not", + autoValueClass, + valueGetter.getSimpleName()); return Optional.empty(); } } - return Optional.of(s -> s); + return Optional.of(Copier.IDENTITY); } // Parameter type is not equal to property type, but might be convertible with copyOf. @@ -455,7 +469,7 @@ class BuilderMethodClassifier { } errorReporter.reportError( setter, - "Parameter type %s of setter method should be %s to match getter %s.%s", + "[AutoValueGetVsSet] Parameter type %s of setter method should be %s to match getter %s.%s", parameterType, targetType, autoValueClass, valueGetter.getSimpleName()); return Optional.empty(); } @@ -465,14 +479,14 @@ class BuilderMethodClassifier { * to the getter's return type using one of the given methods, or {@code Optional.empty()} if the * conversion isn't possible. An error will have been reported in the latter case. */ - private Optional<Function<String, String>> getConvertingSetterFunction( + private Optional<Copier> getConvertingSetterFunction( ImmutableList<ExecutableElement> copyOfMethods, ExecutableElement valueGetter, ExecutableElement setter, TypeMirror parameterType) { DeclaredType targetType = MoreTypes.asDeclared(getterToPropertyType.get(valueGetter)); for (ExecutableElement copyOfMethod : copyOfMethods) { - Optional<Function<String, String>> function = + Optional<Copier> function = getConvertingSetterFunction(copyOfMethod, targetType, parameterType); if (function.isPresent()) { return function; @@ -481,8 +495,8 @@ class BuilderMethodClassifier { String targetTypeSimpleName = targetType.asElement().getSimpleName().toString(); errorReporter.reportError( setter, - "Parameter type %s of setter method should be %s to match getter %s.%s," - + " or it should be a type that can be passed to %s.%s to produce %s", + "[AutoValueGetVsSetOrConvert] Parameter type %s of setter method should be %s to match" + + " getter %s.%s, or it should be a type that can be passed to %s.%s to produce %s", parameterType, targetType, autoValueClass, @@ -516,7 +530,7 @@ class BuilderMethodClassifier { * @return a function that maps a string parameter to a method call using that parameter. For * example it might map {@code foo} to {@code ImmutableList.copyOf(foo)}. */ - private Optional<Function<String, String>> getConvertingSetterFunction( + private Optional<Copier> getConvertingSetterFunction( ExecutableElement copyOfMethod, DeclaredType targetType, TypeMirror parameterType) { // We have a parameter type, for example Set<? extends T>, and we want to know if it can be // passed to the given copyOf method, which might for example be one of these methods from @@ -532,7 +546,15 @@ class BuilderMethodClassifier { if (TypeVariables.canAssignStaticMethodResult( copyOfMethod, parameterType, targetType, typeUtils)) { String method = TypeEncoder.encodeRaw(targetType) + "." + copyOfMethod.getSimpleName(); - return Optional.of(s -> method + "(" + s + ")"); + Function<String, String> callMethod = s -> method + "(" + s + ")"; + // This is a big old hack. We guess that the method can accept a null parameter if it has + // "Nullable" in the name, which java.util.Optional.ofNullable and + // com.google.common.base.Optional.fromNullable do. + Copier copier = + method.contains("Nullable") + ? Copier.acceptingNull(callMethod) + : Copier.notAcceptingNull(callMethod); + return Optional.of(copier); } return Optional.empty(); } diff --git a/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java b/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java index 613d5457..7e5b17c9 100644 --- a/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java +++ b/value/src/main/java/com/google/auto/value/processor/BuilderSpec.java @@ -86,14 +86,17 @@ class BuilderSpec { if (hasAnnotationMirror(containedClass, AUTO_VALUE_BUILDER_NAME)) { if (!CLASS_OR_INTERFACE.contains(containedClass.getKind())) { errorReporter.reportError( - containedClass, "@AutoValue.Builder can only apply to a class or an interface"); + containedClass, + "[AutoValueBuilderClass] @AutoValue.Builder can only apply to a class or an" + + " interface"); } else if (!containedClass.getModifiers().contains(Modifier.STATIC)) { errorReporter.reportError( - containedClass, "@AutoValue.Builder cannot be applied to a non-static class"); + containedClass, + "[AutoValueInnerBuilder] @AutoValue.Builder cannot be applied to a non-static class"); } else if (builderTypeElement.isPresent()) { errorReporter.reportError( containedClass, - "%s already has a Builder: %s", + "[AutoValueTwoBuilders] %s already has a Builder: %s", autoValueClass, builderTypeElement.get()); } else { @@ -218,7 +221,7 @@ class BuilderSpec { if (!builderTypeParamNames.equals(typeArguments)) { errorReporter.reportError( method, - "Builder converter method should return %s%s", + "[AutoValueBuilderConverterReturn] Builder converter method should return %s%s", builderTypeElement, TypeSimplifier.actualTypeParametersString(builderTypeElement)); } @@ -227,7 +230,8 @@ class BuilderSpec { ImmutableSet<ExecutableElement> builderMethods = methods.build(); if (builderMethods.size() > 1) { errorReporter.reportError( - builderMethods.iterator().next(), "There can be at most one builder converter method"); + builderMethods.iterator().next(), + "[AutoValueTwoBuilderConverters] There can be at most one builder converter method"); } this.toBuilderMethods = builderMethods; return builderMethods; @@ -265,7 +269,9 @@ class BuilderSpec { // For now we ignore methods with annotations, because for example we do want to allow // Jackson's @JsonCreator. errorReporter.reportWarning( - method, "Static builder() method should be in the containing class"); + method, + "[AutoValueBuilderInBuilder] Static builder() method should be in the containing" + + " class"); } } this.classifier = optionalClassifier.get(); @@ -276,7 +282,8 @@ class BuilderSpec { for (Element buildMethod : errorElements) { errorReporter.reportError( buildMethod, - "Builder must have a single no-argument method returning %s%s", + "[AutoValueBuilderBuild] Builder must have a single no-argument method returning" + + " %s%s", autoValueClass, typeParamsString()); } @@ -354,6 +361,30 @@ class BuilderSpec { } /** + * Specifies how to copy a parameter value into the target type. This might be the identity, or + * it might be something like {@code ImmutableList.of(...)} or {@code Optional.ofNullable(...)}. + */ + static class Copier { + static final Copier IDENTITY = acceptingNull(x -> x); + + private final Function<String, String> copy; + private final boolean acceptsNull; + + private Copier(Function<String, String> copy, boolean acceptsNull) { + this.copy = copy; + this.acceptsNull = acceptsNull; + } + + static Copier acceptingNull(Function<String, String> copy) { + return new Copier(copy, true); + } + + static Copier notAcceptingNull(Function<String, String> copy) { + return new Copier(copy, false); + } + } + + /** * Information about a property setter, referenced from the autovalue.vm template. A property * called foo (defined by a method {@code T foo()} or {@code T getFoo()}) can have a setter method * {@code foo(T)} or {@code setFoo(T)} that returns the builder type. Additionally, it can have a @@ -369,12 +400,11 @@ class BuilderSpec { private final String parameterTypeString; private final boolean primitiveParameter; private final String nullableAnnotation; - private final Function<String, String> copyFunction; + private final Copier copier; - PropertySetter( - ExecutableElement setter, TypeMirror parameterType, Function<String, String> copyFunction) { + PropertySetter(ExecutableElement setter, TypeMirror parameterType, Copier copier) { this.setter = setter; - this.copyFunction = copyFunction; + this.copier = copier; this.access = SimpleMethod.access(setter); this.name = setter.getSimpleName().toString(); primitiveParameter = parameterType.getKind().isPrimitive(); @@ -423,13 +453,10 @@ class BuilderSpec { } public String copy(AutoValueProcessor.Property property) { - String copy = copyFunction.apply(property.toString()); - - // Add a null guard only in cases where we are using copyOf and the property is @Nullable. - if (property.isNullable() && !copy.equals(property.toString())) { + String copy = copier.copy.apply(property.toString()); + if (property.isNullable() && !copier.acceptsNull) { copy = String.format("(%s == null ? null : %s)", property, copy); } - return copy; } } @@ -450,7 +477,8 @@ class BuilderSpec { if (!sameTypeParameters(autoValueClass, builderTypeElement)) { errorReporter.reportError( builderTypeElement, - "Type parameters of %s must have same names and bounds as type parameters of %s", + "[AutoValueTypeParamMismatch] Type parameters of %s must have same names and bounds as" + + " type parameters of %s", builderTypeElement, autoValueClass); return Optional.empty(); diff --git a/value/src/main/java/com/google/auto/value/processor/PropertyBuilderClassifier.java b/value/src/main/java/com/google/auto/value/processor/PropertyBuilderClassifier.java index dafb5820..2565cddc 100644 --- a/value/src/main/java/com/google/auto/value/processor/PropertyBuilderClassifier.java +++ b/value/src/main/java/com/google/auto/value/processor/PropertyBuilderClassifier.java @@ -198,7 +198,8 @@ class PropertyBuilderClassifier { if (barBuilderTypeMirror.getKind() != TypeKind.DECLARED) { errorReporter.reportError( method, - "Method looks like a property builder, but its return type is not a class or interface"); + "[AutoValueOddBuilderMethod] Method looks like a property builder, but its return type" + + " is not a class or interface"); return Optional.empty(); } DeclaredType barBuilderDeclaredType = MoreTypes.asDeclared(barBuilderTypeMirror); @@ -210,15 +211,15 @@ class PropertyBuilderClassifier { if (barTypeMirror.getKind() != TypeKind.DECLARED) { errorReporter.reportError( method, - "Method looks like a property builder, but the type of property %s is not a class or" - + " interface", + "[AutoValueBadBuilderMethod] Method looks like a property builder, but the type of" + + " property %s is not a class or interface", property); return Optional.empty(); } if (isNullable(barGetter)) { errorReporter.reportError( barGetter, - "Property %s has a property builder so it cannot be @Nullable", + "[AutoValueNullBuilder] Property %s has a property builder so it cannot be @Nullable", property); } TypeElement barTypeElement = MoreTypes.asTypeElement(barTypeMirror); @@ -229,8 +230,8 @@ class PropertyBuilderClassifier { if (build == null || build.getModifiers().contains(Modifier.STATIC)) { errorReporter.reportError( method, - "Method looks like a property builder, but it returns %s which does not have a" - + " non-static build() method", + "[AutoValueBuilderNotBuildable] Method looks like a property builder, but it returns %s" + + " which does not have a non-static build() method", barBuilderTypeElement); return Optional.empty(); } @@ -241,7 +242,8 @@ class PropertyBuilderClassifier { if (!MoreTypes.equivalence().equivalent(barTypeMirror, buildType)) { errorReporter.reportError( method, - "Property builder for %s has type %s whose build() method returns %s instead of %s", + "[AutoValueBuilderWrongType] Property builder for %s has type %s whose build() method" + + " returns %s instead of %s", property, barBuilderTypeElement, buildType, @@ -254,9 +256,9 @@ class PropertyBuilderClassifier { if (!maybeBuilderMaker.isPresent()) { errorReporter.reportError( method, - "Method looks like a property builder, but its type %s does not have a public" - + " constructor and %s does not have a static builder() or newBuilder() method that" - + " returns %s", + "[AutoValueCantMakePropertyBuilder] Method looks like a property builder, but its type" + + " %s does not have a public constructor and %s does not have a static builder() or" + + " newBuilder() method that returns %s", barBuilderTypeElement, barTypeElement, barBuilderTypeElement); diff --git a/value/src/main/java/com/google/auto/value/processor/autoannotation.vm b/value/src/main/java/com/google/auto/value/processor/autoannotation.vm index 1d14d3fb..a953edab 100644 --- a/value/src/main/java/com/google/auto/value/processor/autoannotation.vm +++ b/value/src/main/java/com/google/auto/value/processor/autoannotation.vm @@ -108,7 +108,7 @@ final class $className implements $annotationName { ## annotationType method (defined by the Annotation interface) - @Override + @`java.lang.Override` public Class<? extends $annotationName> annotationType() { return ${annotationName}.class; } @@ -117,7 +117,7 @@ final class $className implements $annotationName { #foreach ($m in $members) - @Override + @`java.lang.Override` public ${m.type} ${m}() { #if ($m.kind == "ARRAY") @@ -162,7 +162,7 @@ final class $className implements $annotationName { #end #end - @Override + @`java.lang.Override` public String toString() { StringBuilder sb = new StringBuilder("@$annotationFullName("); @@ -211,7 +211,7 @@ final class $className implements $annotationName { #end #end - @Override + @`java.lang.Override` public boolean equals(Object o) { if (o == this) { return true; @@ -269,7 +269,7 @@ final class $className implements $annotationName { ## example.) We precompute the invariable part, as an optimization but also in order to avoid ## falling afoul of constant-overflow checks in the compiler. - @Override + @`java.lang.Override` public int hashCode() { return ## If the invariable part is 0, we avoid outputting `return 0 + ...` just because it generates diff --git a/value/src/main/java/com/google/auto/value/processor/autooneof.vm b/value/src/main/java/com/google/auto/value/processor/autooneof.vm index 04cc1949..0249d9eb 100644 --- a/value/src/main/java/com/google/auto/value/processor/autooneof.vm +++ b/value/src/main/java/com/google/auto/value/processor/autooneof.vm @@ -99,7 +99,7 @@ final class $generatedClass { #foreach ($p in $props) - @Override + @`java.lang.Override` $p.access $p.type ${p.getter}() { throw new UnsupportedOperationException(${kindGetter}().toString()); } @@ -128,7 +128,7 @@ final class $generatedClass { private Impl_$p() {} - @Override + @`java.lang.Override` public void ${p.getter}() {} #if ($serializable) @@ -141,7 +141,7 @@ final class $generatedClass { #if ($toString) - @Override + @`java.lang.Override` public String toString() { return "${simpleClassName}{$p.name}"; } @@ -154,7 +154,7 @@ final class $generatedClass { #if ($equals) - @Override + @`java.lang.Override` public boolean equals($equalsParameterType x) { return x == this; } @@ -163,7 +163,7 @@ final class $generatedClass { #if ($hashCode) - @Override + @`java.lang.Override` public int hashCode() { return System.identityHashCode(this); } @@ -178,14 +178,14 @@ final class $generatedClass { this.$p = $p; } - @Override + @`java.lang.Override` public $p.type ${p.getter}() { return $p; } #if ($toString) - @Override + @`java.lang.Override` public String toString() { return "${simpleClassName}{$p.name=" ## + #if ($p.kind == "ARRAY") `java.util.Arrays`.toString(this.$p) #else this.$p #end @@ -196,7 +196,7 @@ final class $generatedClass { #if ($equals) - @Override + @`java.lang.Override` public boolean equals($equalsParameterType x) { if (x instanceof $origClass) { $origClass$wildcardTypes that = ($origClass$wildcardTypes) x; @@ -211,7 +211,7 @@ final class $generatedClass { #if ($hashCode) - @Override + @`java.lang.Override` public int hashCode() { return #hashCodeExpression($p); } @@ -220,7 +220,7 @@ final class $generatedClass { #end - @Override + @`java.lang.Override` public $kindType ${kindGetter}() { return ${kindType}.$propertyToKind[$p.name]; } diff --git a/value/src/main/java/com/google/auto/value/processor/autovalue.vm b/value/src/main/java/com/google/auto/value/processor/autovalue.vm index 80ef79ae..6f50e934 100644 --- a/value/src/main/java/com/google/auto/value/processor/autovalue.vm +++ b/value/src/main/java/com/google/auto/value/processor/autovalue.vm @@ -101,7 +101,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { ${a}## #end - @Override + @`java.lang.Override` ${p.access}${p.type} ${p.getter}() { return $p; } @@ -110,7 +110,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #if ($toString) - @Override + @`java.lang.Override` public `java.lang.String` toString() { return "#if ($identifiers)$simpleClassName#end{" @@ -129,7 +129,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #if ($equals) - @Override + @`java.lang.Override` public boolean equals($equalsParameterType o) { if (o == this) { return true; @@ -162,7 +162,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #if ($hashCode) - @Override + @`java.lang.Override` public int hashCode() { int h$ = 1; @@ -185,7 +185,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #foreach ($m in $toBuilderMethods) - @Override + @`java.lang.Override` ${m.access}${builderTypeName}${builderActualTypes} ${m.name}() { return new Builder${builderActualTypes}(this); } @@ -252,7 +252,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #foreach ($setter in $builderSetters[$p.name]) - @Override + @`java.lang.Override` ${setter.access}${builderTypeName}${builderActualTypes} ## ${setter.name}(${setter.nullableAnnotation}$setter.parameterType $p) { @@ -290,7 +290,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #if ($propertyBuilder) - @Override + @`java.lang.Override` ${propertyBuilder.access}$propertyBuilder.builderType ${p.name}Builder() { if (${propertyBuilder.name} == null) { @@ -337,7 +337,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #if ($builderGetters[$p.name]) - @Override + @`java.lang.Override` ${p.nullableAnnotation}${builderGetters[$p.name].access}$builderGetters[$p.name].type ${p.getter}() { #if ($builderGetters[$p.name].optional) @@ -377,7 +377,7 @@ ${modifiers}class $subclass$formalTypes extends $origClass$actualTypes { #end #end - @Override + @`java.lang.Override` ${buildMethod.get().access}${origClass}${actualTypes} ${buildMethod.get().name}() { #foreach ($p in $props) diff --git a/value/src/main/java/com/google/auto/value/processor/gwtserializer.vm b/value/src/main/java/com/google/auto/value/processor/gwtserializer.vm index 04500360..1265aae4 100644 --- a/value/src/main/java/com/google/auto/value/processor/gwtserializer.vm +++ b/value/src/main/java/com/google/auto/value/processor/gwtserializer.vm @@ -93,26 +93,26 @@ public final class $serializerClass$formalTypes @SuppressWarnings("unused") private int dummy_$classHashString; - @Override + @`java.lang.Override` public void deserializeInstance( `com.google.gwt.user.client.rpc.SerializationStreamReader` streamReader, $subclass$actualTypes instance) { deserialize(streamReader, instance); } - @Override + @`java.lang.Override` public boolean hasCustomInstantiateInstance() { return true; } - @Override + @`java.lang.Override` public $subclass$actualTypes instantiateInstance( `com.google.gwt.user.client.rpc.SerializationStreamReader` streamReader) throws `com.google.gwt.user.client.rpc.SerializationException` { return instantiate(streamReader); } - @Override + @`java.lang.Override` public void serializeInstance( `com.google.gwt.user.client.rpc.SerializationStreamWriter` streamWriter, $subclass$actualTypes instance) |