diff options
author | emcmanus <emcmanus@google.com> | 2020-06-08 11:56:24 -0700 |
---|---|---|
committer | Chris Povirk <beigetangerine@gmail.com> | 2020-06-09 08:37:32 -0400 |
commit | 2f437b5a8276fdd4b4911a86e94ca61d16500180 (patch) | |
tree | e7cc5446d22533001df3cc24ec585f299a187714 | |
parent | b22f969d63d7dc6f2163092637c2ba4c763f00bc (diff) | |
download | auto-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
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(); |