package autodagger.compiler; import com.google.auto.common.MoreElements; import com.google.auto.common.MoreTypes; import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.List; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; /** * @author Lukasz Piliszczuk - lukasz.pili@gmail.com */ final class ProcessingUtil { /** * Types.isSameType() does not work when the origin element that triggers annotation * processing, and calls Types.isSameType() is generated by an other annotation processor * Workaround is to compare the full qualified names of the two types */ public static boolean areTypesEqual(TypeElement typeElement1, TypeElement typeElement2) { return typeElement1.getQualifiedName().equals(typeElement2.getQualifiedName()); } public static boolean areTypesEqual(TypeMirror typeMirror1, TypeMirror typeMirror2) { TypeElement typeElement1 = MoreElements.asType(MoreTypes.asElement(typeMirror1)); TypeElement typeElement2 = MoreElements.asType(MoreTypes.asElement(typeMirror2)); return typeElement1.getQualifiedName().equals(typeElement2.getQualifiedName()); } public static List<TypeName> getTypeNames(List<TypeMirror> typeMirrors) { List<TypeName> typeNames = new ArrayList<>(); if (typeMirrors == null) { return typeNames; } for (TypeMirror typeMirror : typeMirrors) { typeNames.add(TypeName.get(typeMirror)); } return typeNames; } public static List<AdditionSpec> getAdditions(TypeMirror elementTypeMirror, List<AdditionExtractor> extractors) { final List<AdditionSpec> specs = new ArrayList<>(); // for each additions for (AdditionExtractor additionExtractor : extractors) { // for each targets in those additions for (TypeMirror typeMirror : additionExtractor.getTargetTypeMirrors()) { // find if that target is a target for the current component // happens only 1 time per loop if (ProcessingUtil.areTypesEqual(elementTypeMirror, typeMirror)) { // this component is targeted by this addition String name; if (additionExtractor.getProviderMethodName() != null) { name = additionExtractor.getProviderMethodName(); // try to remove "provide" or "provides" from name if (StringUtils.startsWith(name, "provides")) { name = StringUtils.removeStart(name, "provides"); } else if (StringUtils.startsWith(name, "provide")) { name = StringUtils.removeStart(name, "provide"); } name = StringUtils.uncapitalize(name); } else { name = StringUtils.uncapitalize(additionExtractor.getAdditionElement().getSimpleName().toString()); } TypeName typeName; ClassName className = ClassName.get(additionExtractor.getAdditionElement()); if (additionExtractor.getParameterizedTypeMirrors().isEmpty()) { typeName = className; } else { // with parameterized types TypeName[] types = new TypeName[additionExtractor.getParameterizedTypeMirrors().size()]; int i = 0; for (TypeMirror tm : additionExtractor.getParameterizedTypeMirrors()) { types[i++] = TypeName.get(tm); } typeName = ParameterizedTypeName.get(className, types); } AdditionSpec spec = new AdditionSpec(name, typeName); // add qualifier if it exists if (additionExtractor.getQualifierAnnotationMirror() != null) { spec.setQualifierAnnotationSpec(AnnotationSpec.get(additionExtractor.getQualifierAnnotationMirror())); } specs.add(spec); } } } return specs; } public static List<AdditionSpec> getAdditions(Element element, List<AdditionExtractor> extractors) { return getAdditions(element.asType(), extractors); } }