Search in sources :

Example 1 with ExecutableType

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();
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) ParameterSpec(com.squareup.javapoet.ParameterSpec) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeSpec(com.squareup.javapoet.TypeSpec) Nonnull(javax.annotation.Nonnull)

Example 2 with ExecutableType

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();
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) MethodSpec(com.squareup.javapoet.MethodSpec) ParameterSpec(com.squareup.javapoet.ParameterSpec) ExecutableElement(javax.lang.model.element.ExecutableElement) Nonnull(javax.annotation.Nonnull)

Example 3 with ExecutableType

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);
        }
    }
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) TypeParameterElement(javax.lang.model.element.TypeParameterElement) DeclaredType(javax.lang.model.type.DeclaredType)

Example 4 with ExecutableType

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);
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) Arrays(java.util.Arrays) PackageElement(javax.lang.model.element.PackageElement) AbstractProcessor(javax.annotation.processing.AbstractProcessor) Modifier(javax.lang.model.element.Modifier) VariableElement(javax.lang.model.element.VariableElement) HashMap(java.util.HashMap) TypeElement(javax.lang.model.element.TypeElement) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) Elements(javax.lang.model.util.Elements) ArrayList(java.util.ArrayList) SupportedSourceVersion(javax.annotation.processing.SupportedSourceVersion) Kind(javax.tools.Diagnostic.Kind) Map(java.util.Map) DeclaredType(javax.lang.model.type.DeclaredType) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) PrintWriter(java.io.PrintWriter) ElementKind(javax.lang.model.element.ElementKind) ExecutableType(javax.lang.model.type.ExecutableType) StringWriter(java.io.StringWriter) Collection(java.util.Collection) ExecutableElement(javax.lang.model.element.ExecutableElement) Set(java.util.Set) IOException(java.io.IOException) Element(javax.lang.model.element.Element) TypeSpec(com.squareup.javapoet.TypeSpec) Processor(javax.annotation.processing.Processor) Types(javax.lang.model.util.Types) Collectors(java.util.stream.Collectors) AnnotationMirror(javax.lang.model.element.AnnotationMirror) TypeKind(javax.lang.model.type.TypeKind) JavaFile(com.squareup.javapoet.JavaFile) SourceVersion(javax.lang.model.SourceVersion) List(java.util.List) TypeMirror(javax.lang.model.type.TypeMirror) RoundEnvironment(javax.annotation.processing.RoundEnvironment) AutoService(com.google.auto.service.AutoService) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Nonnull(javax.annotation.Nonnull)

Example 5 with ExecutableType

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);
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) Nonnull(javax.annotation.Nonnull)

Aggregations

ExecutableType (javax.lang.model.type.ExecutableType)68 ExecutableElement (javax.lang.model.element.ExecutableElement)53 DeclaredType (javax.lang.model.type.DeclaredType)41 TypeElement (javax.lang.model.element.TypeElement)39 TypeMirror (javax.lang.model.type.TypeMirror)39 Element (javax.lang.model.element.Element)29 VariableElement (javax.lang.model.element.VariableElement)27 TypeSpec (com.squareup.javapoet.TypeSpec)13 Nonnull (javax.annotation.Nonnull)13 PackageElement (javax.lang.model.element.PackageElement)13 HashMap (java.util.HashMap)12 Map (java.util.Map)12 MethodSpec (com.squareup.javapoet.MethodSpec)11 AnnotationMirror (javax.lang.model.element.AnnotationMirror)11 IOException (java.io.IOException)10 ArrayList (java.util.ArrayList)10 HashSet (java.util.HashSet)10 Nullable (javax.annotation.Nullable)10 JavaFile (com.squareup.javapoet.JavaFile)9 List (java.util.List)9