Fix: toStringForLoggingLazy() was broken on some compilers, e.g. Eclipse

It seems different compilers generate different method names for
lambdas. This change avoids the use of lambdas.

Change-Id: I4159adfa279cf48a7a6dab2d3ca76e1d3483a053
This commit is contained in:
Joerg Zieren
2019-10-11 14:14:35 +02:00
parent 5ffd069cc4
commit ea277c4397

View File

@@ -183,63 +183,66 @@ public abstract class Metadata {
* @return string representation of this instance that is suitable for logging * @return string representation of this instance that is suitable for logging
*/ */
LazyArg<String> toStringForLoggingLazy() { LazyArg<String> toStringForLoggingLazy() {
return LazyArgs.lazy( // Don't use a lambda because different compilers generate different method names for lambdas,
() -> { // e.g. "lambda$myFunction$0" vs. just "lambda$0" in Eclipse. We need to identify the method
// Append class name. // by name to skip it and avoid infinite recursion.
String className = getClass().getSimpleName(); return LazyArgs.lazy(this::toStringForLoggingImpl);
if (className.startsWith("AutoValue_")) { }
className = className.substring(10);
}
ToStringHelper stringHelper = MoreObjects.toStringHelper(className);
// Append key-value pairs for field which are set. private String toStringForLoggingImpl() {
Method[] methods = Metadata.class.getDeclaredMethods(); // Append class name.
Arrays.sort(methods, Comparator.comparing(Method::getName)); String className = getClass().getSimpleName();
for (Method method : methods) { if (className.startsWith("AutoValue_")) {
if (Modifier.isStatic(method.getModifiers())) { className = className.substring(10);
// skip static method }
continue; ToStringHelper stringHelper = MoreObjects.toStringHelper(className);
}
if (method.getName().matches("(lambda\\$)?toStringForLoggingLazy(\\$0)?")) { // Append key-value pairs for field which are set.
// skip toStringForLoggingLazy() and the lambda itself Method[] methods = Metadata.class.getDeclaredMethods();
continue; Arrays.sort(methods, Comparator.comparing(Method::getName));
} for (Method method : methods) {
if (Modifier.isStatic(method.getModifiers())) {
// skip static method
continue;
}
if (method.getReturnType().equals(Void.TYPE) || method.getParameterCount() > 0) { if (method.getName().equals("toStringForLoggingLazy")
// skip method since it's not a getter || method.getName().equals("toStringForLoggingImpl")) {
continue; // Don't call myself in infinite recursion.
} continue;
}
method.setAccessible(true); if (method.getReturnType().equals(Void.TYPE) || method.getParameterCount() > 0) {
// skip method since it's not a getter
continue;
}
Object returnValue; method.setAccessible(true);
try {
returnValue = method.invoke(this);
} catch (IllegalArgumentException
| IllegalAccessException
| InvocationTargetException e) {
// should never happen
throw new IllegalStateException(e);
}
if (returnValue instanceof Optional) { Object returnValue;
Optional<?> fieldValueOptional = (Optional<?>) returnValue; try {
if (!fieldValueOptional.isPresent()) { returnValue = method.invoke(this);
// drop this key-value pair } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
continue; // should never happen
} throw new IllegalStateException(e);
}
// format as 'key=value' instead of 'key=Optional[value]' if (returnValue instanceof Optional) {
stringHelper.add(method.getName(), fieldValueOptional.get()); Optional<?> fieldValueOptional = (Optional<?>) returnValue;
} else { if (!fieldValueOptional.isPresent()) {
// not an Optional value, keep as is // drop this key-value pair
stringHelper.add(method.getName(), returnValue); continue;
} }
}
return stringHelper.toString(); // format as 'key=value' instead of 'key=Optional[value]'
}); stringHelper.add(method.getName(), fieldValueOptional.get());
} else {
// not an Optional value, keep as is
stringHelper.add(method.getName(), returnValue);
}
}
return stringHelper.toString();
} }
public static Metadata.Builder builder() { public static Metadata.Builder builder() {