/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.litho.specmodels.processor;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import com.facebook.litho.specmodels.internal.ImmutableList;
import com.facebook.litho.annotations.FromEvent;
import com.facebook.litho.annotations.OnEvent;
import com.facebook.litho.annotations.Param;
import com.facebook.litho.annotations.Prop;
import com.facebook.litho.annotations.State;
import com.facebook.litho.annotations.TreeProp;
import com.facebook.litho.specmodels.model.EventDeclarationModel;
import com.facebook.litho.specmodels.model.EventMethodModel;
import com.facebook.litho.specmodels.model.MethodParamModel;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeName;
import static com.facebook.litho.specmodels.processor.MethodExtractorUtils.getMethodParams;
/**
* Extracts event methods from the given input.
*/
public class EventMethodExtractor {
private static final List<Class<? extends Annotation>> METHOD_PARAM_ANNOTATIONS =
new ArrayList<>();
static {
METHOD_PARAM_ANNOTATIONS.add(FromEvent.class);
METHOD_PARAM_ANNOTATIONS.add(Param.class);
METHOD_PARAM_ANNOTATIONS.add(Prop.class);
METHOD_PARAM_ANNOTATIONS.add(State.class);
METHOD_PARAM_ANNOTATIONS.add(TreeProp.class);
}
/**
* Get the delegate methods from the given {@link TypeElement}.
*/
public static ImmutableList<EventMethodModel> getOnEventMethods(
Elements elements,
TypeElement typeElement,
List<Class<? extends Annotation>> permittedInterStageInputAnnotations) {
final List<EventMethodModel> delegateMethods = new ArrayList<>();
for (Element enclosedElement : typeElement.getEnclosedElements()) {
if (enclosedElement.getKind() != ElementKind.METHOD) {
continue;
}
final OnEvent onEventAnnotation = enclosedElement.getAnnotation(OnEvent.class);
if (onEventAnnotation != null) {
final ExecutableElement executableElement = (ExecutableElement) enclosedElement;
final List<MethodParamModel> methodParams =
getMethodParams(
executableElement,
getPermittedMethodParamAnnotations(permittedInterStageInputAnnotations),
permittedInterStageInputAnnotations);
final DeclaredType eventClassDeclaredType = ProcessorUtils.getAnnotationParameter(
elements,
executableElement,
OnEvent.class,
"value");
final Element eventClass = eventClassDeclaredType.asElement();
final EventMethodModel eventMethod =
new EventMethodModel(
new EventDeclarationModel(
ClassName.bestGuess(eventClass.toString()),
EventDeclarationsExtractor.getReturnType(elements, eventClass),
EventDeclarationsExtractor.getFields(eventClass),
eventClass),
ImmutableList.copyOf(new ArrayList<>(executableElement.getModifiers())),
executableElement.getSimpleName(),
TypeName.get(executableElement.getReturnType()),
ImmutableList.copyOf(methodParams),
executableElement);
delegateMethods.add(eventMethod);
}
}
return ImmutableList.copyOf(delegateMethods);
}
private static List<Class<? extends Annotation>> getPermittedMethodParamAnnotations(
List<Class<? extends Annotation>> permittedInterStageInputAnnotations) {
final List<Class<? extends Annotation>> permittedMethodParamAnnotations =
new ArrayList<>(METHOD_PARAM_ANNOTATIONS);
permittedMethodParamAnnotations.addAll(permittedInterStageInputAnnotations);
return permittedMethodParamAnnotations;
}
}