class EclipseHack
extends java.lang.Object
To work around the problem, we access Eclipse-specific APIs to find the original source code of
the class with the @AutoValue
annotation, and we do just enough parsing of that code to
be able to pick out the abstract method declarations so we can determine their order. The code
to access Eclipse-specific APIs will fail in environments other than Eclipse (for example, javac)
and the methods will be left in the order they came in, which in these other environments should
already be the correct order.
This is obviously a giant hack, and the right thing would be for the Eclipse compiler to be
fixed. The approach here works, but is vulnerable to future changes in the Eclipse API. If
@AutoValue
constructor calls like new AutoValue_Foo(...)
suddenly start being
redlined in a new Eclipse version then the likely cause is that the APIs have changed and this
hack will need to be updated to track the change.
Modifier and Type | Class and Description |
---|---|
private class |
EclipseHack.BinaryPropertyOrderer |
private static interface |
EclipseHack.PropertyOrderer |
private class |
EclipseHack.SourcePropertyOrderer |
Modifier and Type | Field and Description |
---|---|
private javax.annotation.processing.ProcessingEnvironment |
processingEnv |
Constructor and Description |
---|
EclipseHack(javax.annotation.processing.ProcessingEnvironment processingEnv) |
Modifier and Type | Method and Description |
---|---|
private EclipseHack.PropertyOrderer |
getPropertyOrderer(javax.lang.model.element.TypeElement type) |
(package private) com.google.common.collect.ImmutableMap<javax.lang.model.element.ExecutableElement,javax.lang.model.type.TypeMirror> |
methodReturnTypes(java.util.Set<javax.lang.model.element.ExecutableElement> methods,
javax.lang.model.element.TypeElement autoValueType)
Returns a map containing the real return types of the given methods, knowing that they appear
in the given type.
|
private java.util.Map<javax.lang.model.element.Name,javax.lang.model.element.ExecutableElement> |
noArgMethodsIn(javax.lang.model.element.TypeElement autoValueType)
Constructs a map from name to method of the no-argument methods in the given type.
|
(package private) void |
reorderProperties(java.util.List<AutoValueProcessor.Property> properties)
Reorders the properties (abstract methods) in the given list to correspond to the order found
by parsing the source code of the given type.
|
private void |
reorderProperties(javax.lang.model.element.TypeElement type,
java.util.List<AutoValueProcessor.Property> properties) |
private final javax.annotation.processing.ProcessingEnvironment processingEnv
EclipseHack(javax.annotation.processing.ProcessingEnvironment processingEnv)
com.google.common.collect.ImmutableMap<javax.lang.model.element.ExecutableElement,javax.lang.model.type.TypeMirror> methodReturnTypes(java.util.Set<javax.lang.model.element.ExecutableElement> methods, javax.lang.model.element.TypeElement autoValueType)
StringIterator implements Iterator<String>
then we want the next()
method
to map to String, rather than the T
that it returns as inherited from
Iterator<T>
. This method is in EclipseHack because if it weren't for
this Eclipse bug it would
be trivial. Unfortunately, versions of Eclipse up to at least 4.5 have a bug where the
Types.asMemberOf(javax.lang.model.type.DeclaredType, javax.lang.model.element.Element)
method throws IllegalArgumentException if given a method that is
inherited from an interface. Fortunately, Eclipse's implementation of
Elements.getAllMembers(javax.lang.model.element.TypeElement)
does the type substitution that asMemberOf
would have
done. But javac's implementation doesn't. So we try the way that would work if Eclipse weren't
buggy, and only if we get IllegalArgumentException do we use getAllMembers
.private java.util.Map<javax.lang.model.element.Name,javax.lang.model.element.ExecutableElement> noArgMethodsIn(javax.lang.model.element.TypeElement autoValueType)
Elements.getAllMembers(javax.lang.model.element.TypeElement)
will not compare
equal to the original ExecutableElement if getAllMembers
substituted type parameters,
as it does in Eclipse.void reorderProperties(java.util.List<AutoValueProcessor.Property> properties)
private void reorderProperties(javax.lang.model.element.TypeElement type, java.util.List<AutoValueProcessor.Property> properties)
private EclipseHack.PropertyOrderer getPropertyOrderer(javax.lang.model.element.TypeElement type)