use of javax.lang.model.type.ExecutableType in project react4j by react4j.
the class Generator method buildBuilderStepInterface.
@Nonnull
private static TypeSpec buildBuilderStepInterface(@Nonnull final ComponentDescriptor descriptor, @Nonnull final Step step) {
final int stepIndex = step.getIndex();
final TypeSpec.Builder builder = TypeSpec.interfaceBuilder("Builder" + stepIndex);
builder.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
builder.addTypeVariables(ProcessorUtil.getTypeArgumentsAsNames(descriptor.getDeclaredType()));
if (!descriptor.getDeclaredType().getTypeArguments().isEmpty()) {
builder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "unused").build());
}
for (final StepMethod stepMethod : step.getMethods()) {
final StepMethodType stepMethodType = stepMethod.getStepMethodType();
// Magically handle the step method named build
if (stepMethod.isBuildIntrinsic()) {
builder.addMethod(buildStepInterfaceMethod("build", step, stepMethodType, m -> {
}).build());
} else {
builder.addMethod(buildStepInterfaceMethod(stepMethod.getName(), step, stepMethodType, m -> {
final ExecutableType propMethodType = stepMethod.getPropMethodType();
if (null != propMethodType) {
ProcessorUtil.copyTypeParameters(propMethodType, m);
}
if (stepMethod.isChildrenIntrinsic()) {
m.varargs();
}
final ParameterSpec.Builder parameter = ParameterSpec.builder(stepMethod.getType(), stepMethod.getName());
final ExecutableElement propMethod = stepMethod.getPropMethod();
if (null != propMethod) {
ProcessorUtil.copyDocumentedAnnotations(propMethod, parameter);
} else if (stepMethod.isKeyIntrinsic() || stepMethod.isChildrenStreamIntrinsic()) {
parameter.addAnnotation(NONNULL_CLASSNAME);
} else if (stepMethod.isChildOfChildrenIntrinsic()) {
parameter.addAnnotation(NULLABLE_CLASSNAME);
}
m.addParameter(parameter.build());
}).build());
}
}
return builder.build();
}
use of javax.lang.model.type.ExecutableType in project react4j by react4j.
the class Generator method buildStaticStepMethodMethod.
@Nonnull
private static MethodSpec buildStaticStepMethodMethod(@Nonnull final ComponentDescriptor descriptor, @Nonnull final Step step, @Nonnull final StepMethod stepMethod) {
final MethodSpec.Builder method = MethodSpec.methodBuilder(stepMethod.getName()).addAnnotation(NONNULL_CLASSNAME);
method.addModifiers(Modifier.STATIC);
if (descriptor.getDeclaredType().asElement().getModifiers().contains(Modifier.PUBLIC)) {
method.addModifiers(Modifier.PUBLIC);
}
final ExecutableType propMethodType = stepMethod.getPropMethodType();
if (null != propMethodType) {
ProcessorUtil.copyTypeParameters(propMethodType, method);
}
ProcessorUtil.copyTypeParameters(descriptor.getElement(), method);
if (!stepMethod.isBuildIntrinsic()) {
final ParameterSpec.Builder parameter = ParameterSpec.builder(stepMethod.getType(), stepMethod.getName(), Modifier.FINAL);
final ExecutableElement propMethod = stepMethod.getPropMethod();
if (null != propMethod) {
ProcessorUtil.copyDocumentedAnnotations(propMethod, parameter);
} else if (stepMethod.isKeyIntrinsic() || stepMethod.isChildrenStreamIntrinsic()) {
parameter.addAnnotation(NONNULL_CLASSNAME);
} else if (stepMethod.isChildOfChildrenIntrinsic()) {
parameter.addAnnotation(NULLABLE_CLASSNAME);
}
method.addParameter(parameter.build());
}
final String infix = asTypeArgumentsInfix(descriptor.getDeclaredType());
if (stepMethod.isBuildIntrinsic()) {
method.addStatement("return new $T" + infix + "().build()", ClassName.bestGuess("Builder"));
} else {
method.addStatement("return new $T" + infix + "().$N( $N )", ClassName.bestGuess("Builder"), stepMethod.getName(), stepMethod.getName());
}
configureStepMethodReturns(method, step, stepMethod.getStepMethodType());
return method.build();
}
use of javax.lang.model.type.ExecutableType in project react4j by react4j.
the class ProcessorUtil method enumerateMethods.
private static void enumerateMethods(@Nonnull final TypeElement scope, @Nonnull final Types typeUtils, @Nonnull final TypeElement element, @Nonnull final Map<String, ExecutableElement> methods) {
final TypeMirror superclass = element.getSuperclass();
if (TypeKind.NONE != superclass.getKind()) {
enumerateMethods(scope, typeUtils, (TypeElement) ((DeclaredType) superclass).asElement(), methods);
}
for (final TypeMirror interfaceType : element.getInterfaces()) {
final TypeElement interfaceElement = (TypeElement) ((DeclaredType) interfaceType).asElement();
enumerateMethods(scope, typeUtils, interfaceElement, methods);
}
for (final Element member : element.getEnclosedElements()) {
if (member.getKind() == ElementKind.METHOD) {
final ExecutableType methodType = (ExecutableType) typeUtils.asMemberOf((DeclaredType) scope.asType(), member);
methods.put(member.getSimpleName() + methodType.toString(), (ExecutableElement) member);
}
}
}
use of javax.lang.model.type.ExecutableType in project react4j by react4j.
the class ReactProcessor method createCallbackDescriptor.
@Nonnull
private CallbackDescriptor createCallbackDescriptor(@Nonnull final ComponentDescriptor descriptor, @Nonnull final ExecutableElement method) {
verifyNoDuplicateAnnotations(method);
final String name = deriveCallbackName(method);
final TypeElement callbackType = getCallbackType(method);
final ExecutableType methodType = (ExecutableType) processingEnv.getTypeUtils().asMemberOf(descriptor.getDeclaredType(), method);
final List<ExecutableElement> callbackMethods = ProcessorUtil.getMethods(callbackType, processingEnv.getTypeUtils()).stream().filter(m11 -> m11.getModifiers().contains(Modifier.ABSTRACT)).collect(Collectors.toList());
if (callbackMethods.isEmpty()) {
throw new ReactProcessorException("Method annotated with @Callback specified type " + callbackType.getQualifiedName() + " that has no abstract method and " + "thus is not a functional interface", method);
} else if (callbackMethods.size() > 1) {
throw new ReactProcessorException("Method annotated with @Callback specified type " + callbackType.getQualifiedName() + " that has more than 1 abstract " + "method and thus is not a functional interface", method);
}
final boolean initCallbackContext = shouldInitCallbackContext(descriptor, method);
if (initCallbackContext && descriptor.isArezComponent() && null != ProcessorUtil.findAnnotationByType(method, Constants.ACTION_ANNOTATION_CLASSNAME)) {
final String message = "@Callback target is also annotated with @arez.annotations.Action but the @Callback parameter " + "'initCallbackContext' is not set to Feature.DISABLE which would stop react4j from also " + "annotating the method with @Action. Please remove @Action or change the 'initCallbackContext' to " + "Feature.DISABLE.";
throw new ReactProcessorException(message, method);
}
return new CallbackDescriptor(name, method, methodType, callbackType, callbackMethods.get(0), initCallbackContext);
}
use of javax.lang.model.type.ExecutableType in project react4j by react4j.
the class ReactProcessor method createPropDescriptor.
@Nonnull
private PropDescriptor createPropDescriptor(@Nonnull final ComponentDescriptor descriptor, @Nonnull final ExecutableElement method) {
final String name = derivePropName(method);
final ExecutableType methodType = (ExecutableType) processingEnv.getTypeUtils().asMemberOf(descriptor.getDeclaredType(), method);
verifyNoDuplicateAnnotations(method);
MethodChecks.mustBeAbstract(Constants.PROP_ANNOTATION_CLASSNAME, method);
MethodChecks.mustNotHaveAnyParameters(Constants.PROP_ANNOTATION_CLASSNAME, method);
MethodChecks.mustReturnAValue(Constants.PROP_ANNOTATION_CLASSNAME, method);
MethodChecks.mustNotThrowAnyExceptions(Constants.PROP_ANNOTATION_CLASSNAME, method);
if ("key".equals(name)) {
throw new ReactProcessorException("@Prop named 'key' is invalid as the name references value used in the " + "reconciliation process. This value can be accessed via Component.getKey()", method);
} else if ("build".equals(name)) {
throw new ReactProcessorException("@Prop named 'build' is invalid as it conflicts with the method named " + "build() that is used in the generated Builder classes", method);
} else if ("child".equals(name) && (methodType.getReturnType().getKind() != TypeKind.DECLARED && !"react4j.core.ReactNode".equals(methodType.getReturnType().toString()))) {
throw new ReactProcessorException("@Prop named 'child' should be of type react4j.core.ReactNode", method);
} else if ("children".equals(name) && (methodType.getReturnType().getKind() != TypeKind.DECLARED && !"react4j.core.ReactNode[]".equals(methodType.getReturnType().toString()))) {
throw new ReactProcessorException("@Prop named 'children' should be of type react4j.core.ReactNode[]", method);
}
final Element propType = processingEnv.getTypeUtils().asElement(method.getReturnType());
return new PropDescriptor(name, method, methodType, propType);
}
Aggregations