173 lines
7.7 KiB
Java
173 lines
7.7 KiB
Java
|
|
import com.google.auto.service.AutoService;
|
||
|
|
|
||
|
|
import javax.annotation.processing.*;
|
||
|
|
import javax.lang.model.SourceVersion;
|
||
|
|
import javax.lang.model.element.*;
|
||
|
|
import java.util.*;
|
||
|
|
import java.util.stream.Collectors;
|
||
|
|
|
||
|
|
|
||
|
|
import hdvtdev.telegram.handler.annotations.*;
|
||
|
|
|
||
|
|
@AutoService(Processor.class)
|
||
|
|
@SupportedAnnotationTypes({
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnChosenInlineResult",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnChatMemberUpdated",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnChatBoostRemoved",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnPreCheckoutQuery",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnBusinessConnection",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnPaidMediaPurchased",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnUpdate",
|
||
|
|
"hdvtdev.telegram.handler.annotations.BotCommand",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnPoll",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnMessage",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnChatJoinRequest",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnChatBoostUpdated",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnCallbackQuery",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnShippingQuery",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnInlineQuery",
|
||
|
|
"hdvtdev.telegram.handler.annotations.OnPollAnswer"})
|
||
|
|
@SupportedSourceVersion(SourceVersion.RELEASE_21)
|
||
|
|
public class EventHandlersProcessor extends AbstractProcessor {
|
||
|
|
|
||
|
|
private final StringBuilder sb = new StringBuilder();
|
||
|
|
|
||
|
|
private static final String PACKAGE = "hdvtdev.telegram.handler.annotations.";
|
||
|
|
private static final String HANDLER_PACKAGE = "hdvtdev.telegram.handler.";
|
||
|
|
|
||
|
|
private static final Set<String> SUPPORTED_ANNOTATIONS = Set.of(
|
||
|
|
OnChosenInlineResult.class,
|
||
|
|
OnChatMemberUpdated.class,
|
||
|
|
OnChatBoostRemoved.class,
|
||
|
|
OnPreCheckoutQuery.class,
|
||
|
|
OnBusinessConnection.class,
|
||
|
|
OnPaidMediaPurchased.class,
|
||
|
|
OnUpdate.class,
|
||
|
|
OnPoll.class,
|
||
|
|
OnMessage.class,
|
||
|
|
OnChatJoinRequest.class,
|
||
|
|
OnChatBoostUpdated.class,
|
||
|
|
OnCallbackQuery.class,
|
||
|
|
OnShippingQuery.class,
|
||
|
|
OnInlineQuery.class,
|
||
|
|
OnPollAnswer.class
|
||
|
|
).stream().map(Class::getName).collect(Collectors.toSet());
|
||
|
|
|
||
|
|
private static final Map<String, String> SUPPORTED_PARAMETERS = Map.ofEntries(
|
||
|
|
Map.entry("Update", "hdvtdev.telegram.core.objects.Update"),
|
||
|
|
Map.entry("InlineQuery", "hdvtdev.telegram.core.objects.InlineQuery"),
|
||
|
|
Map.entry("ChatMemberUpdated", "hdvtdev.telegram.core.objects.chat.ChatMemberUpdated"),
|
||
|
|
Map.entry("ChatBoostRemoved", "hdvtdev.telegram.core.objects.chatboost.ChatBoostRemoved"),
|
||
|
|
Map.entry("PreCheckoutQuery", "hdvtdev.telegram.core.objects.payment.PreCheckoutQuery"),
|
||
|
|
Map.entry("BusinessConnection", "hdvtdev.telegram.core.objects.business.BusinessConnection"),
|
||
|
|
Map.entry("PaidMediaPurchased", "hdvtdev.telegram.core.objects.media.paidmedia.PaidMediaPurchased"),
|
||
|
|
Map.entry("Poll", "hdvtdev.telegram.core.objects.poll.Poll"),
|
||
|
|
Map.entry("Message", "hdvtdev.telegram.core.objects.Message"),
|
||
|
|
Map.entry("ChatJoinRequest", "hdvtdev.telegram.core.objects.chat.ChatJoinRequest"),
|
||
|
|
Map.entry("ChatBoostUpdated", "hdvtdev.telegram.core.objects.chatboost.ChatBoostUpdated"),
|
||
|
|
Map.entry("CallbackQuery", "hdvtdev.telegram.core.objects.callback.CallbackQuery"),
|
||
|
|
Map.entry("ShippingQuery", "hdvtdev.telegram.core.objects.payment.ShippingQuery"),
|
||
|
|
Map.entry("PollAnswer", "hdvtdev.telegram.core.objects.poll.PollAnswer"),
|
||
|
|
Map.entry("ChosenInlineResult", "hdvtdev.telegram.core.objects.ChosenInlineResult")
|
||
|
|
);
|
||
|
|
|
||
|
|
public static String getFullParameterName(String simpleName) {
|
||
|
|
return SUPPORTED_PARAMETERS.get(simpleName);
|
||
|
|
}
|
||
|
|
|
||
|
|
private Messager messager;
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||
|
|
super.init(processingEnv);
|
||
|
|
messager = processingEnv.getMessager();
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
|
||
|
|
messager.printNote("Called");
|
||
|
|
for (Element element : roundEnvironment.getRootElements()) {
|
||
|
|
for (Element enclosedElement : element.getEnclosedElements()) {
|
||
|
|
if (enclosedElement.getKind() == ElementKind.METHOD) {
|
||
|
|
processMethod((ExecutableElement) enclosedElement);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (roundEnvironment.processingOver()) {
|
||
|
|
write();
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void write() {
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
private void processMethod(ExecutableElement methodElement) {
|
||
|
|
String methodName = methodElement.getSimpleName().toString();
|
||
|
|
|
||
|
|
List<AnnotationMirror> foundAnnotations = new ArrayList<>();
|
||
|
|
for (AnnotationMirror mirror : methodElement.getAnnotationMirrors()) {
|
||
|
|
String mirrorAnnotationName = Util.getAnnotationMirrorName(mirror);
|
||
|
|
if (SUPPORTED_ANNOTATIONS.contains(PACKAGE + mirrorAnnotationName)) {
|
||
|
|
foundAnnotations.add(mirror);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (foundAnnotations.size() > 1) {
|
||
|
|
List<String> annotationNames = new ArrayList<>();
|
||
|
|
for (AnnotationMirror mirror : foundAnnotations) {
|
||
|
|
annotationNames.add("@" + Util.getAnnotationMirrorName(mirror));
|
||
|
|
}
|
||
|
|
|
||
|
|
messager.printError(String.format("Method %s cannot have multiple mutually exclusive annotations. Found: %s. Please leave only one.",
|
||
|
|
methodName, String.join(", ", annotationNames)), methodElement);
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (foundAnnotations.size() == 1) {
|
||
|
|
AnnotationMirror annotation = foundAnnotations.getFirst();
|
||
|
|
String annotationSimpleName = Util.getAnnotationMirrorName(annotation);
|
||
|
|
|
||
|
|
var params = methodElement.getParameters();
|
||
|
|
if (params.isEmpty()) {
|
||
|
|
messager.printError(String.format("Method %s, annotated with @%s, must have at least one parameter.",
|
||
|
|
methodName, annotationSimpleName), methodElement);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
String firstParameterType = Util.getParameterClassName(params.getFirst().asType());
|
||
|
|
String requiredParameter = Util.checkParameter(annotationSimpleName, firstParameterType);
|
||
|
|
|
||
|
|
if (!requiredParameter.isEmpty()) {
|
||
|
|
messager.printError(String.format("Incorrect parameter type for method %s. Annotation @%s requires %s, but found %s.",
|
||
|
|
methodName, annotationSimpleName, requiredParameter, firstParameterType), params.getFirst());
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!annotationSimpleName.equals("BotCommand")) {
|
||
|
|
String paramName = params.getFirst().getSimpleName().toString();
|
||
|
|
Set<String> filters = new HashSet<>();
|
||
|
|
|
||
|
|
AnnotationValue vv = Util.getAnnotationValue(annotation, "filters");
|
||
|
|
@SuppressWarnings("unchecked")
|
||
|
|
List<? extends AnnotationValue> enumValues = vv == null ? List.of() : (List<? extends AnnotationValue>) vv.getValue();
|
||
|
|
for (AnnotationValue v : enumValues) {
|
||
|
|
if (v.getValue() instanceof VariableElement enumConstant) {
|
||
|
|
filters.add(enumConstant.getSimpleName().toString());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
sb.append(Generator.generateVoid(methodName, String.format("%s %s", firstParameterType, paramName),
|
||
|
|
Generator.generateFilterBlock(filters, paramName)));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|