package io.kaif.mobile.retrofit.processor; import com.google.auto.service.AutoService; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.TypeSpec; import java.io.IOException; import java.io.Writer; import java.util.LinkedHashSet; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import retrofit2.http.DELETE; import retrofit2.http.GET; import retrofit2.http.HEAD; import retrofit2.http.POST; import retrofit2.http.PUT; @AutoService(Processor.class) public class RetrofitServiceProcessor extends AbstractProcessor { private Elements elementUtils; private Filer filer; private Messager messager; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); elementUtils = processingEnv.getElementUtils(); filer = processingEnv.getFiler(); messager = processingEnv.getMessager(); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { annotations.stream() .flatMap(typeElement -> roundEnv.getElementsAnnotatedWith(typeElement).stream()) .filter(element -> element.getKind() == ElementKind.METHOD) .map(Element::getEnclosingElement) .distinct() .filter(element -> element.getKind() == ElementKind.INTERFACE) .filter(element -> !RetrofitServiceInterface.isGenerated(element)) .map(element -> new RetrofitServiceInterface((TypeElement) element)) .forEach(this::generateCode); return false; } private void generateCode(RetrofitServiceInterface retrofitServiceInterface) { TypeSpec typeSpec = retrofitServiceInterface.createRetryStaleInterface(); TypeElement annotatedClassElement = retrofitServiceInterface.getAnnotatedClassElement(); JavaFile javaFile = JavaFile.builder(elementUtils.getPackageOf(annotatedClassElement) .getQualifiedName() .toString(), typeSpec).build(); try { JavaFileObject jfo = filer.createSourceFile(retrofitServiceInterface.getQualifiedName()); try (Writer writer = jfo.openWriter()) { javaFile.writeTo(writer); } } catch (IOException e) { error(annotatedClassElement, e.getMessage()); } } @Override public Set<String> getSupportedAnnotationTypes() { Set<String> annotations = new LinkedHashSet<String>(); annotations.add(GET.class.getCanonicalName()); annotations.add(PUT.class.getCanonicalName()); annotations.add(POST.class.getCanonicalName()); annotations.add(DELETE.class.getCanonicalName()); annotations.add(HEAD.class.getCanonicalName()); return annotations; } private void error(Element e, String msg, Object... args) { messager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args), e); } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } }