aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremcmanus <emcmanus@google.com>2020-06-08 11:56:24 -0700
committerChris Povirk <beigetangerine@gmail.com>2020-06-09 08:37:32 -0400
commit2f437b5a8276fdd4b4911a86e94ca61d16500180 (patch)
treee7cc5446d22533001df3cc24ec585f299a187714
parentb22f969d63d7dc6f2163092637c2ba4c763f00bc (diff)
downloadauto-2f437b5a8276fdd4b4911a86e94ca61d16500180.tar.gz
Change error reporting methods to use format strings.
RELNOTES=n/a ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=315322251
-rw-r--r--value/src/main/java/com/google/auto/value/processor/AutoOneOfProcessor.java31
-rw-r--r--value/src/main/java/com/google/auto/value/processor/AutoValueOrOneOfProcessor.java63
-rw-r--r--value/src/main/java/com/google/auto/value/processor/AutoValueProcessor.java77
-rw-r--r--value/src/main/java/com/google/auto/value/processor/BuilderMethodClassifier.java108
-rw-r--r--value/src/main/java/com/google/auto/value/processor/BuilderSpec.java38
-rw-r--r--value/src/main/java/com/google/auto/value/processor/ErrorReporter.java33
-rw-r--r--value/src/main/java/com/google/auto/value/processor/PropertyBuilderClassifier.java54
7 files changed, 203 insertions, 201 deletions
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 a41127c7..d05ed43c 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,7 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor {
void processType(TypeElement autoOneOfType) {
if (autoOneOfType.getKind() != ElementKind.CLASS) {
errorReporter()
- .abortWithError("@" + AUTO_ONE_OF_NAME + " only applies to classes", autoOneOfType);
+ .abortWithError(autoOneOfType, "@" + AUTO_ONE_OF_NAME + " only applies to classes");
}
checkModifiersIfNested(autoOneOfType);
DeclaredType kindMirror = mirrorForKindType(autoOneOfType);
@@ -128,9 +128,9 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor {
// but it has happened in the past and can crash the compiler.
errorReporter()
.abortWithError(
+ autoOneOfType,
"annotation processor for @AutoOneOf was invoked with a type"
- + " that does not have that annotation; this is probably a compiler bug",
- autoOneOfType);
+ + " that does not have that annotation; this is probably a compiler bug");
}
AnnotationValue kindValue =
AnnotationMirrors.getAnnotationValue(oneOfAnnotation.get(), "value");
@@ -183,8 +183,9 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor {
if (!transformedEnumConstants.containsKey(transformed)) {
errorReporter()
.reportError(
- "Enum has no constant with name corresponding to property '" + property + "'",
- kindElement);
+ kindElement,
+ "Enum has no constant with name corresponding to property '%s'",
+ property);
}
});
// Enum constants that have no property
@@ -193,10 +194,9 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor {
if (!transformedPropertyNames.containsKey(transformed)) {
errorReporter()
.reportError(
- "Name of enum constant '"
- + constant.getSimpleName()
- + "' does not correspond to any property name",
- constant);
+ constant,
+ "Name of enum constant '%s' does not correspond to any property name",
+ constant.getSimpleName());
}
});
throw new AbortProcessingException();
@@ -220,15 +220,17 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor {
case 0:
errorReporter()
.reportError(
- autoOneOfType + " must have a no-arg abstract method returning " + kindMirror,
- autoOneOfType);
+ autoOneOfType,
+ "%s must have a no-arg abstract method returning %s",
+ autoOneOfType,
+ kindMirror);
break;
case 1:
return Iterables.getOnlyElement(kindGetters);
default:
for (ExecutableElement getter : kindGetters) {
errorReporter()
- .reportError("More than one abstract method returns " + kindMirror, getter);
+ .reportError(getter, "More than one abstract method returns %s", kindMirror);
}
}
throw new AbortProcessingException();
@@ -252,8 +254,7 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor {
// implement this alien method.
errorReporter()
.reportWarning(
- "Abstract methods in @AutoOneOf classes must have no parameters",
- method);
+ method, "Abstract methods in @AutoOneOf classes must have no parameters");
}
}
errorReporter().abortIfAnyError();
@@ -277,7 +278,7 @@ public class AutoOneOfProcessor extends AutoValueOrOneOfProcessor {
@Override
Optional<String> nullableAnnotationForMethod(ExecutableElement propertyMethod) {
if (nullableAnnotationFor(propertyMethod, propertyMethod.getReturnType()).isPresent()) {
- errorReporter().reportError("@AutoOneOf properties cannot be @Nullable", propertyMethod);
+ errorReporter().reportError(propertyMethod, "@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 6e708ba0..4214c128 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
@@ -300,12 +300,10 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
// was in deferredTypes.
for (TypeElement type : deferredTypes) {
errorReporter.reportError(
- "Did not generate @"
- + simpleAnnotationName
- + " class for "
- + type.getQualifiedName()
- + " because it references undefined types",
- type);
+ type,
+ "Did not generate @%s class for %s because it references undefined types",
+ simpleAnnotationName,
+ type.getQualifiedName());
}
return false;
}
@@ -333,7 +331,7 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
} catch (RuntimeException e) {
String trace = Throwables.getStackTraceAsString(e);
errorReporter.reportError(
- "@" + simpleAnnotationName + " processor threw an exception: " + trace, type);
+ type, "@%s processor threw an exception: %s", simpleAnnotationName, trace);
throw e;
}
}
@@ -401,7 +399,7 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
nullableAnnotation);
props.add(p);
if (p.isNullable() && returnType.getKind().isPrimitive()) {
- errorReporter().reportError("Primitive types cannot be @Nullable", propertyMethod);
+ errorReporter().reportError(propertyMethod, "Primitive types cannot be @Nullable");
}
});
return props.build();
@@ -511,10 +509,15 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
String name = allPrefixed ? nameWithoutPrefix(methodName) : methodName;
ExecutableElement old = map.put(name, method);
if (old != null) {
- String message = "More than one @" + simpleAnnotationName + " property called " + name;
- errorReporter.reportError(message, method);
+ List<ExecutableElement> contexts = new ArrayList<>(Arrays.asList(method));
if (reportedDups.add(name)) {
- errorReporter.reportError(message, old);
+ contexts.add(old);
+ }
+ // Report the error for both of the methods. If this is a third or further occurrence,
+ // 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);
}
}
}
@@ -619,16 +622,16 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
if (enclosingKind.isClass() || enclosingKind.isInterface()) {
if (type.getModifiers().contains(Modifier.PRIVATE)) {
errorReporter.abortWithError(
- "@" + simpleAnnotationName + " class must not be private", type);
+ type, "@%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(
- "@" + simpleAnnotationName + " class must not be nested in a private class", type);
+ type, "@%s class must not be nested in a private class", simpleAnnotationName);
}
if (!type.getModifiers().contains(Modifier.STATIC)) {
errorReporter.abortWithError(
- "Nested @" + simpleAnnotationName + " class must be static", type);
+ type, "Nested @%s class must be static", simpleAnnotationName);
}
}
// In principle type.getEnclosingElement() could be an ExecutableElement (for a class
@@ -768,10 +771,9 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
warnAboutPrimitiveArrays(autoValueClass, getter);
} else {
errorReporter.reportError(
- "An @"
- + simpleAnnotationName
- + " class cannot define an array-valued property unless it is a primitive array",
- getter);
+ getter,
+ "An @%s class cannot define an array-valued property unless it is a primitive array",
+ simpleAnnotationName);
}
}
}
@@ -792,20 +794,17 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
// inherited class is not being recompiled. Instead, in this case we point to the @AutoValue
// class itself, and we include extra text in the error message that shows the full name of
// the inherited method.
- String warning =
- "An @"
- + simpleAnnotationName
- + " property that is a primitive array returns the original array, which can"
+ boolean sameClass = getter.getEnclosingElement().equals(autoValueClass);
+ Element element = sameClass ? getter : autoValueClass;
+ 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.";
- boolean sameClass = getter.getEnclosingElement().equals(autoValueClass);
- if (sameClass) {
- errorReporter.reportWarning(warning, getter);
- } else {
- errorReporter.reportWarning(
- warning + " Method: " + getter.getEnclosingElement() + "." + getter, autoValueClass);
- }
+ + " with an immutable type, perhaps a simple wrapper around the original array.%s",
+ simpleAnnotationName,
+ context);
}
}
@@ -837,7 +836,7 @@ abstract class AutoValueOrOneOfProcessor extends AbstractProcessor {
return value + "L";
} else {
errorReporter.reportError(
- "serialVersionUID must be a static final long compile-time constant", field);
+ field, "serialVersionUID must be a static final long compile-time constant");
break;
}
}
@@ -1103,7 +1102,7 @@ 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(
- "Could not write generated class " + className + ": " + e, originatingType);
+ originatingType, "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 cbdc7734..f3b396ca 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
@@ -114,15 +114,17 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor {
try {
extensions = extensionsFromLoader(loaderForExtensions);
} catch (RuntimeException | Error e) {
- StringBuilder warning = new StringBuilder();
- warning.append(
- "An exception occurred while looking for AutoValue extensions."
- + " No extensions will function.");
- if (e instanceof ServiceConfigurationError) {
- warning.append(" This may be due to a corrupt jar file in the compiler's classpath.");
- }
- warning.append("\n").append(Throwables.getStackTraceAsString(e));
- errorReporter().reportWarning(warning.toString(), null);
+ String explain =
+ (e instanceof ServiceConfigurationError)
+ ? " This may be due to a corrupt jar file in the compiler's classpath."
+ : "";
+ errorReporter()
+ .reportWarning(
+ null,
+ "An exception occurred while looking for AutoValue extensions."
+ + " No extensions will function.%s\n%s",
+ explain,
+ Throwables.getStackTraceAsString(e));
extensions = ImmutableList.of();
}
}
@@ -167,22 +169,21 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor {
// but it has happened in the past and can crash the compiler.
errorReporter()
.abortWithError(
+ type,
"annotation processor for @AutoValue was invoked with a type"
- + " that does not have that annotation; this is probably a compiler bug",
- type);
+ + " that does not have that annotation; this is probably a compiler bug");
}
if (type.getKind() != ElementKind.CLASS) {
- errorReporter().abortWithError("@AutoValue only applies to classes", type);
+ errorReporter().abortWithError(type, "@AutoValue only applies to classes");
}
if (ancestorIsAutoValue(type)) {
- errorReporter().abortWithError("One @AutoValue class may not extend another", type);
+ errorReporter().abortWithError(type, "One @AutoValue class may not extend another");
}
if (implementsAnnotation(type)) {
errorReporter()
.abortWithError(
- "@AutoValue may not be used to implement an annotation"
- + " interface; try using @AutoAnnotation instead",
- type);
+ type, "@AutoValue may not be used to implement an annotation"
+ + " interface; try using @AutoAnnotation instead");
}
checkModifiersIfNested(type);
@@ -331,9 +332,9 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor {
default:
errorReporter()
.reportError(
- "More than one extension wants to generate the final class: "
- + finalExtensions.stream().map(this::extensionName).collect(joining(", ")),
- type);
+ type,
+ "More than one extension wants to generate the final class: %s",
+ finalExtensions.stream().map(this::extensionName).collect(joining(", ")));
break;
}
return ImmutableList.copyOf(applicableExtensions);
@@ -353,11 +354,10 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor {
if (propertyMethod == null) {
errorReporter()
.reportError(
- "Extension "
- + extensionName(extension)
- + " wants to consume a property that does not exist: "
- + consumedProperty,
- type);
+ type,
+ "Extension %s wants to consume a property that does not exist: %s",
+ extensionName(extension),
+ consumedProperty);
} else {
consumedHere.add(propertyMethod);
}
@@ -366,12 +366,11 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor {
if (!abstractMethods.contains(consumedMethod)) {
errorReporter()
.reportError(
- "Extension "
- + extensionName(extension)
- + " wants to consume a method that is not one of the abstract methods in this"
- + " class: "
- + consumedMethod,
- type);
+ type,
+ "Extension %s wants to consume a method that is not one of the abstract methods"
+ + " in this class: %s",
+ extensionName(extension),
+ consumedMethod);
} else {
consumedHere.add(consumedMethod);
}
@@ -379,10 +378,10 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor {
for (ExecutableElement repeat : intersection(consumed, consumedHere)) {
errorReporter()
.reportError(
- "Extension "
- + extensionName(extension)
- + " wants to consume a method that was already consumed by another extension",
- repeat);
+ repeat,
+ "Extension %s wants to consume a method that was already consumed by another"
+ + " extension",
+ extensionName(extension));
}
consumed.addAll(consumedHere);
}
@@ -404,11 +403,11 @@ public class AutoValueProcessor extends AutoValueOrOneOfProcessor {
// ElementUtils.override that sometimes fails to recognize that one method overrides
// 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 message = "Abstract method is neither a property getter nor a Builder converter";
- if (extensionsPresent) {
- message += ", and no extension consumed it";
- }
- errorReporter().reportWarning(message, method);
+ 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().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 97a50e8b..724a3225 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
@@ -196,8 +196,8 @@ class BuilderMethodClassifier {
this.settersPrefixed = true;
} else {
errorReporter.reportError(
- "If any setter methods use the setFoo convention then all must",
- propertyNameToUnprefixedSetters.values().iterator().next().getSetter());
+ propertyNameToUnprefixedSetters.values().iterator().next().getSetter(),
+ "If any setter methods use the setFoo convention then all must");
return false;
}
getterToPropertyName.forEach(
@@ -217,23 +217,22 @@ class BuilderMethodClassifier {
|| propertyBuilder.getCopyAll() != null);
boolean needToMakeBarBuilder = (autoValueHasToBuilder || hasSetter);
if (needToMakeBarBuilder && !canMakeBarBuilder) {
- String error =
- String.format(
- "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);
- errorReporter.reportError(error, propertyBuilder.getPropertyBuilderMethod());
+ 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",
+ propertyBuilder.getBuilderTypeMirror(),
+ propertyType);
}
} else if (!hasSetter) {
// We have neither barBuilder() nor setBar(Bar), so we should complain.
String setterName = settersPrefixed ? prefixWithSet(property) : property;
- String error =
- String.format(
- "Expected a method with this signature: %s%s %s(%s), or a %sBuilder() method",
- builderType, typeParamsString(), setterName, propertyType, property);
- errorReporter.reportError(error, builderType);
+ errorReporter.reportError(
+ builderType,
+ "Expected a method with this signature: %s%s %s(%s), or a %sBuilder() method",
+ builderType, typeParamsString(), setterName, propertyType, property);
}
});
return errorReporter.errorCount() == startErrorCount;
@@ -249,7 +248,7 @@ class BuilderMethodClassifier {
classifyMethodOneArg(method);
break;
default:
- errorReporter.reportError("Builder methods must have 0 or 1 parameters", method);
+ errorReporter.reportError(method, "Builder methods must have 0 or 1 parameters");
}
}
@@ -295,13 +294,12 @@ class BuilderMethodClassifier {
if (TYPE_EQUIVALENCE.equivalent(returnType, autoValueClass.asType())) {
buildMethods.add(method);
} else {
- String error =
- String.format(
- "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());
- errorReporter.reportError(error, method);
+ 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());
}
}
@@ -334,12 +332,11 @@ class BuilderMethodClassifier {
return;
}
}
- String error =
- String.format(
- "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);
- errorReporter.reportError(error, builderGetter);
+ 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);
}
/**
@@ -375,7 +372,7 @@ 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 does not correspond to a property of " + autoValueClass, method);
+ method, "Method does not correspond to a property of %s", autoValueClass);
checkForFailedJavaBean(method);
return;
}
@@ -390,7 +387,7 @@ class BuilderMethodClassifier {
propertyName, new PropertySetter(method, parameterType, function.get()));
} else {
errorReporter.reportError(
- "Setter methods must return " + builderType + typeParamsString(), method);
+ method, "Setter methods must return %s%s", builderType, typeParamsString());
}
}
}
@@ -406,11 +403,11 @@ class BuilderMethodClassifier {
AutoValueProcessor.prefixedGettersIn(allGetters);
if (prefixedGetters.size() < allGetters.size()
&& prefixedGetters.size() >= allGetters.size() / 2) {
- String note =
+ errorReporter.reportNote(
+ rejectedSetter,
"This might be because you are using the getFoo() convention"
- + " for some but not all methods. These methods don't follow the convention: "
- + difference(allGetters, prefixedGetters);
- errorReporter.reportNote(note, rejectedSetter);
+ + " for some but not all methods. These methods don't follow the convention: %s",
+ difference(allGetters, prefixedGetters));
}
}
@@ -441,11 +438,10 @@ class BuilderMethodClassifier {
boolean nullableProperty =
nullableAnnotationFor(valueGetter, valueGetter.getReturnType()).isPresent();
if (!nullableProperty) {
- String error =
- String.format(
- "Parameter of setter method is @Nullable but property method %s.%s() is not",
- autoValueClass, valueGetter.getSimpleName());
- errorReporter.reportError(error, setter);
+ errorReporter.reportError(
+ setter,
+ "Parameter of setter method is @Nullable but property method %s.%s() is not",
+ autoValueClass, valueGetter.getSimpleName());
return Optional.empty();
}
}
@@ -457,11 +453,10 @@ class BuilderMethodClassifier {
if (!copyOfMethods.isEmpty()) {
return getConvertingSetterFunction(copyOfMethods, valueGetter, setter, parameterType);
}
- String error =
- String.format(
- "Parameter type %s of setter method should be %s to match getter %s.%s",
- parameterType, targetType, autoValueClass, valueGetter.getSimpleName());
- errorReporter.reportError(error, setter);
+ errorReporter.reportError(
+ setter,
+ "Parameter type %s of setter method should be %s to match getter %s.%s",
+ parameterType, targetType, autoValueClass, valueGetter.getSimpleName());
return Optional.empty();
}
@@ -484,18 +479,17 @@ class BuilderMethodClassifier {
}
}
String targetTypeSimpleName = targetType.asElement().getSimpleName().toString();
- String error =
- String.format(
- "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,
- valueGetter.getSimpleName(),
- targetTypeSimpleName,
- copyOfMethods.get(0).getSimpleName(),
- targetType);
- errorReporter.reportError(error, setter);
+ 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",
+ parameterType,
+ targetType,
+ autoValueClass,
+ valueGetter.getSimpleName(),
+ targetTypeSimpleName,
+ copyOfMethods.get(0).getSimpleName(),
+ targetType);
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 f218891c..613d5457 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,16 @@ class BuilderSpec {
if (hasAnnotationMirror(containedClass, AUTO_VALUE_BUILDER_NAME)) {
if (!CLASS_OR_INTERFACE.contains(containedClass.getKind())) {
errorReporter.reportError(
- "@AutoValue.Builder can only apply to a class or an interface", containedClass);
+ containedClass, "@AutoValue.Builder can only apply to a class or an interface");
} else if (!containedClass.getModifiers().contains(Modifier.STATIC)) {
errorReporter.reportError(
- "@AutoValue.Builder cannot be applied to a non-static class", containedClass);
+ containedClass, "@AutoValue.Builder cannot be applied to a non-static class");
} else if (builderTypeElement.isPresent()) {
errorReporter.reportError(
- autoValueClass + " already has a Builder: " + builderTypeElement.get(),
- containedClass);
+ containedClass,
+ "%s already has a Builder: %s",
+ autoValueClass,
+ builderTypeElement.get());
} else {
builderTypeElement = Optional.of(containedClass);
}
@@ -215,17 +217,17 @@ class BuilderSpec {
.collect(toList());
if (!builderTypeParamNames.equals(typeArguments)) {
errorReporter.reportError(
- "Builder converter method should return "
- + builderTypeElement
- + TypeSimplifier.actualTypeParametersString(builderTypeElement),
- method);
+ method,
+ "Builder converter method should return %s%s",
+ builderTypeElement,
+ TypeSimplifier.actualTypeParametersString(builderTypeElement));
}
}
}
ImmutableSet<ExecutableElement> builderMethods = methods.build();
if (builderMethods.size() > 1) {
errorReporter.reportError(
- "There can be at most one builder converter method", builderMethods.iterator().next());
+ builderMethods.iterator().next(), "There can be at most one builder converter method");
}
this.toBuilderMethods = builderMethods;
return builderMethods;
@@ -263,7 +265,7 @@ class BuilderSpec {
// For now we ignore methods with annotations, because for example we do want to allow
// Jackson's @JsonCreator.
errorReporter.reportWarning(
- "Static builder() method should be in the containing class", method);
+ method, "Static builder() method should be in the containing class");
}
}
this.classifier = optionalClassifier.get();
@@ -273,10 +275,10 @@ class BuilderSpec {
buildMethods.isEmpty() ? ImmutableSet.of(builderTypeElement) : buildMethods;
for (Element buildMethod : errorElements) {
errorReporter.reportError(
- "Builder must have a single no-argument method returning "
- + autoValueClass
- + typeParamsString(),
- buildMethod);
+ buildMethod,
+ "Builder must have a single no-argument method returning %s%s",
+ autoValueClass,
+ typeParamsString());
}
return;
}
@@ -447,10 +449,10 @@ class BuilderSpec {
if (!sameTypeParameters(autoValueClass, builderTypeElement)) {
errorReporter.reportError(
- String.format(
- "Type parameters of %s must have same names and bounds as type parameters of %s",
- builderTypeElement, autoValueClass),
- builderTypeElement);
+ builderTypeElement,
+ "Type parameters of %s must have same names and bounds as type parameters of %s",
+ builderTypeElement,
+ autoValueClass);
return Optional.empty();
}
return Optional.of(new Builder(builderTypeElement));
diff --git a/value/src/main/java/com/google/auto/value/processor/ErrorReporter.java b/value/src/main/java/com/google/auto/value/processor/ErrorReporter.java
index 81169071..e2a3d839 100644
--- a/value/src/main/java/com/google/auto/value/processor/ErrorReporter.java
+++ b/value/src/main/java/com/google/auto/value/processor/ErrorReporter.java
@@ -15,6 +15,7 @@
*/
package com.google.auto.value.processor;
+import com.google.errorprone.annotations.FormatMethod;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
@@ -36,21 +37,25 @@ class ErrorReporter {
/**
* Issue a compilation note.
*
- * @param msg the text of the note
* @param e the element to which it pertains
+ * @param format the format string for the text of the note
+ * @param args arguments for the format string
*/
- void reportNote(String msg, Element e) {
- messager.printMessage(Diagnostic.Kind.NOTE, msg, e);
+ @FormatMethod
+ void reportNote(Element e, String format, Object... args) {
+ messager.printMessage(Diagnostic.Kind.NOTE, String.format(format, args), e);
}
/**
* Issue a compilation warning.
*
- * @param msg the text of the warning
* @param e the element to which it pertains
+ * @param format the format string for the text of the warning
+ * @param args arguments for the format string
*/
- void reportWarning(String msg, Element e) {
- messager.printMessage(Diagnostic.Kind.WARNING, msg, e);
+ @FormatMethod
+ void reportWarning(Element e, String format, Object... args) {
+ messager.printMessage(Diagnostic.Kind.WARNING, String.format(format, args), e);
}
/**
@@ -59,11 +64,13 @@ class ErrorReporter {
* CompilationTest for any new call to reportError(...) to ensure that we continue correctly after
* an error.
*
- * @param msg the text of the warning
* @param e the element to which it pertains
+ * @param format the format string for the text of the warning
+ * @param args arguments for the format string
*/
- void reportError(String msg, Element e) {
- messager.printMessage(Diagnostic.Kind.ERROR, msg, e);
+ @FormatMethod
+ void reportError(Element e, String format, Object... args) {
+ messager.printMessage(Diagnostic.Kind.ERROR, String.format(format, args), e);
errorCount++;
}
@@ -71,11 +78,13 @@ class ErrorReporter {
* Issue a compilation error and abandon the processing of this class. This does not prevent the
* processing of other classes.
*
- * @param msg the text of the error
* @param e the element to which it pertains
+ * @param format the format string for the text of the error
+ * @param args arguments for the format string
*/
- void abortWithError(String msg, Element e) {
- reportError(msg, e);
+ @FormatMethod
+ void abortWithError(Element e, String format, Object... args) {
+ reportError(e, format, args);
throw new AbortProcessingException();
}
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 7558da26..dafb5820 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
@@ -197,8 +197,8 @@ class PropertyBuilderClassifier {
TypeMirror barBuilderTypeMirror = builderMethodClassifier.builderMethodReturnType(method);
if (barBuilderTypeMirror.getKind() != TypeKind.DECLARED) {
errorReporter.reportError(
- "Method looks like a property builder, but its return type is not a class or interface",
- method);
+ method,
+ "Method looks like a property builder, but its return type is not a class or interface");
return Optional.empty();
}
DeclaredType barBuilderDeclaredType = MoreTypes.asDeclared(barBuilderTypeMirror);
@@ -209,16 +209,17 @@ class PropertyBuilderClassifier {
TypeMirror barTypeMirror = getterToPropertyType.get(barGetter);
if (barTypeMirror.getKind() != TypeKind.DECLARED) {
errorReporter.reportError(
- "Method looks like a property builder, but the type of property "
- + property
- + " is not a class or interface",
- method);
+ method,
+ "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(
- "Property " + property + " has a property builder so it cannot be @Nullable",
- barGetter);
+ barGetter,
+ "Property %s has a property builder so it cannot be @Nullable",
+ property);
}
TypeElement barTypeElement = MoreTypes.asTypeElement(barTypeMirror);
Map<String, ExecutableElement> barNoArgMethods = noArgMethodsOf(barTypeElement);
@@ -227,10 +228,10 @@ class PropertyBuilderClassifier {
ExecutableElement build = barBuilderNoArgMethods.get("build");
if (build == null || build.getModifiers().contains(Modifier.STATIC)) {
errorReporter.reportError(
- "Method looks like a property builder, but it returns "
- + barBuilderTypeElement
- + " which does not have a non-static build() method",
- method);
+ method,
+ "Method looks like a property builder, but it returns %s which does not have a"
+ + " non-static build() method",
+ barBuilderTypeElement);
return Optional.empty();
}
@@ -239,15 +240,12 @@ class PropertyBuilderClassifier {
TypeMirror buildType = eclipseHack.methodReturnType(build, barBuilderDeclaredType);
if (!MoreTypes.equivalence().equivalent(barTypeMirror, buildType)) {
errorReporter.reportError(
- "Property builder for "
- + property
- + " has type "
- + barBuilderTypeElement
- + " whose build() method returns "
- + buildType
- + " instead of "
- + barTypeMirror,
- method);
+ method,
+ "Property builder for %s has type %s whose build() method returns %s instead of %s",
+ property,
+ barBuilderTypeElement,
+ buildType,
+ barTypeMirror);
return Optional.empty();
}
@@ -255,13 +253,13 @@ class PropertyBuilderClassifier {
builderMaker(barNoArgMethods, barBuilderTypeElement);
if (!maybeBuilderMaker.isPresent()) {
errorReporter.reportError(
- "Method looks like a property builder, but its type "
- + barBuilderTypeElement
- + " does not have a public constructor and "
- + barTypeElement
- + " does not have a static builder() or newBuilder() method that returns "
- + barBuilderTypeElement,
- method);
+ 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",
+ barBuilderTypeElement,
+ barTypeElement,
+ barBuilderTypeElement);
return Optional.empty();
}
ExecutableElement builderMaker = maybeBuilderMaker.get();