#460 add workaround for TypeElements that occasionally seem "empty" during incremental compilation in Eclipse JDT

This commit is contained in:
Andreas Gudian 2015-02-21 20:59:10 +01:00 committed by Gunnar Morling
parent b7e1388e0f
commit bfaa524cb7
3 changed files with 32 additions and 1 deletions

View File

@ -58,6 +58,7 @@ import org.mapstruct.ap.util.AnnotationProcessingException;
import org.mapstruct.ap.util.SpecificCompilerWorkarounds;
import static org.mapstruct.ap.util.SpecificCompilerWorkarounds.erasure;
import static org.mapstruct.ap.util.SpecificCompilerWorkarounds.replaceTypeElementIfNecessary;
/**
* Factory creating {@link Type} instances.
@ -258,7 +259,8 @@ public class TypeFactory {
* @return the ExecutableType representing the method as part of usedMapper
*/
public ExecutableType getMethodType(TypeElement usedMapper, ExecutableElement method) {
TypeMirror asMemberOf = typeUtils.asMemberOf( (DeclaredType) usedMapper.asType(), method );
DeclaredType asType = (DeclaredType) replaceTypeElementIfNecessary( elementUtils, usedMapper ).asType();
TypeMirror asMemberOf = typeUtils.asMemberOf( asType, method );
ExecutableType methodType = asMemberOf.accept( new ExecutableTypeRetrievalVisitor(), null );
return methodType;
}

View File

@ -35,6 +35,7 @@ import javax.lang.model.util.SimpleElementVisitor6;
import javax.lang.model.util.SimpleTypeVisitor6;
import static javax.lang.model.util.ElementFilter.methodsIn;
import static org.mapstruct.ap.util.SpecificCompilerWorkarounds.replaceTypeElementIfNecessary;
/**
* Provides functionality around {@link ExecutableElement}s.
@ -185,6 +186,7 @@ public class Executables {
*/
public static List<ExecutableElement> getAllEnclosedExecutableElements(Elements elementUtils, TypeElement element) {
List<ExecutableElement> enclosedElements = new ArrayList<ExecutableElement>();
element = replaceTypeElementIfNecessary( elementUtils, element );
addEnclosedElementsInHierarchy( elementUtils, enclosedElements, element, element );
return enclosedElements;
@ -192,6 +194,10 @@ public class Executables {
private static void addEnclosedElementsInHierarchy(Elements elementUtils, List<ExecutableElement> alreadyAdded,
TypeElement element, TypeElement parentType) {
if ( element != parentType ) { // otherwise the element was already checked for replacement
element = replaceTypeElementIfNecessary( elementUtils, element );
}
addNotYetOverridden( elementUtils, alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
if ( hasNonObjectSuperclass( element ) ) {

View File

@ -18,8 +18,10 @@
*/
package org.mapstruct.ap.util;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
/**
@ -72,4 +74,25 @@ public class SpecificCompilerWorkarounds {
return types.erasure( t );
}
}
/**
* When running during Eclipse Incremental Compilation, we might get a TypeElement that has an UnresolvedTypeBinding
* and which is not automatically resolved. In that case, getEnclosedElements returns an empty list. We take that as
* a hint to check if the TypeElement resolved by FQN might have any enclosed elements and, if so, return the
* resolved element.
*
* @param elementUtils element utils
* @param element the original element
* @return the element freshly resolved using the qualified name, if the original element did not return any
* enclosed elements, whereas the resolved element does return enclosed elements.
*/
public static TypeElement replaceTypeElementIfNecessary(Elements elementUtils, TypeElement element) {
if ( element.getEnclosedElements().isEmpty() ) {
TypeElement resolvedByName = elementUtils.getTypeElement( element.getQualifiedName() );
if ( resolvedByName != null && !resolvedByName.getEnclosedElements().isEmpty() ) {
return resolvedByName;
}
}
return element;
}
}