Search in sources :

Example 46 with ExecutableType

use of javax.lang.model.type.ExecutableType in project react4j by react4j.

the class ReactProcessor method determineCallbacks.

private void determineCallbacks(@Nonnull final ComponentDescriptor descriptor) {
    final List<CallbackDescriptor> callbacks = ProcessorUtil.getMethods(descriptor.getElement(), processingEnv.getTypeUtils()).stream().filter(m -> null != ProcessorUtil.findAnnotationByType(m, Constants.CALLBACK_ANNOTATION_CLASSNAME)).map(m -> createCallbackDescriptor(descriptor, m)).collect(Collectors.toList());
    for (final CallbackDescriptor callback : callbacks) {
        final ExecutableElement method = callback.getMethod();
        final TypeElement callbackType = getCallbackType(method);
        if (ElementKind.INTERFACE != callbackType.getKind()) {
            throw new ReactProcessorException("The @Callback specified an invalid type that is not an interface.", callback.getMethod());
        }
        if (null == ProcessorUtil.findAnnotationByType(callbackType, Constants.JS_FUNCTION_CLASSNAME)) {
            throw new ReactProcessorException("The @Callback specified an invalid type that is not annotated " + "with the annotation jsinterop.annotations.JsFunction.", callback.getMethod());
        }
        final CallbackDescriptor matched = callbacks.stream().filter(h -> h != callback && h.getName().equals(callback.getName())).findAny().orElse(null);
        if (null != matched) {
            throw new ReactProcessorException("The @Callback has the same name as the callback defined by " + matched.getMethod() + ".", callback.getMethod());
        }
        final CallbackDescriptor matched2 = callbacks.stream().filter(h -> h != callback && h.getMethod().getSimpleName().equals(callback.getMethod().getSimpleName())).findAny().orElse(null);
        if (null != matched2) {
            throw new ReactProcessorException("The @Callback has the same method name as the callback defined " + "by " + matched2.getMethod() + ".", callback.getMethod());
        }
        final ExecutableType methodType = callback.getMethodType();
        final List<? extends TypeMirror> parameters = methodType.getParameterTypes();
        if (!parameters.isEmpty()) {
            // Our annotated callback method has parameters so they should exactly align
            // in count and type with the parameters in the callback method
            final ExecutableElement target = callback.getCallbackMethod();
            final List<? extends VariableElement> targetParameters = target.getParameters();
            if (targetParameters.size() != parameters.size()) {
                throw new ReactProcessorException("The @Callback target has " + parameters.size() + " parameters " + "but the type parameter specified a callback with method type " + callback.getCallbackType().getQualifiedName() + " that has a " + "callback method with " + targetParameters.size() + " parameters. The " + "@Callback target should have zero parameters or match the number " + "of parameter in the target method " + target.getSimpleName() + ".", callback.getMethod());
            }
            for (int i = 0; i < parameters.size(); i++) {
                final TypeMirror parameterType = parameters.get(i);
                final VariableElement element = targetParameters.get(i);
                final TypeMirror targetParameterType = element.asType();
                final TypeMirror targetErased = processingEnv.getTypeUtils().erasure(targetParameterType);
                final TypeMirror parameterErased = processingEnv.getTypeUtils().erasure(parameterType);
                if (!processingEnv.getTypeUtils().isAssignable(targetErased, parameterErased)) {
                    throw new ReactProcessorException("The @Callback target parameter named " + callback.getMethod().getParameters().get(i).getSimpleName() + " of type " + parameterType + " is not assignable from target type " + targetParameterType + " of parameter " + element.getSimpleName() + " in method " + callback.getCallbackType().getQualifiedName() + "." + target.getSimpleName() + ".", callback.getMethod());
                }
            }
        }
    }
    descriptor.setCallbacks(callbacks);
}
Also used : 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) ExecutableType(javax.lang.model.type.ExecutableType) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) VariableElement(javax.lang.model.element.VariableElement)

Example 47 with ExecutableType

use of javax.lang.model.type.ExecutableType in project react4j by react4j.

the class ReactProcessor method determineDefaultPropsMethods.

private void determineDefaultPropsMethods(@Nonnull final ComponentDescriptor descriptor) {
    final Types typeUtils = processingEnv.getTypeUtils();
    final List<ExecutableElement> defaultPropsMethods = ProcessorUtil.getMethods(descriptor.getElement(), typeUtils).stream().filter(m -> null != ProcessorUtil.findAnnotationByType(m, Constants.PROP_DEFAULT_ANNOTATION_CLASSNAME)).collect(Collectors.toList());
    for (final ExecutableElement method : defaultPropsMethods) {
        final String name = derivePropDefaultName(method);
        final PropDescriptor prop = descriptor.findPropNamed(name);
        if (null == prop) {
            throw new ReactProcessorException("@PropDefault target for prop named '" + name + "' has no corresponding " + "@Prop annotated method.", method);
        }
        final ExecutableType methodType = (ExecutableType) typeUtils.asMemberOf(descriptor.getDeclaredType(), method);
        if (!processingEnv.getTypeUtils().isAssignable(methodType.getReturnType(), prop.getMethodType().getReturnType())) {
            throw new ReactProcessorException("@PropDefault target has a return type that is not assignable to the " + "return type of the associated @Prop annotated method.", method);
        }
        prop.setDefaultMethod(method);
    }
}
Also used : 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) ExecutableType(javax.lang.model.type.ExecutableType) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) Types(javax.lang.model.util.Types) ExecutableElement(javax.lang.model.element.ExecutableElement)

Example 48 with ExecutableType

use of javax.lang.model.type.ExecutableType in project react4j by react4j.

the class ReactProcessor method linkStateMethods.

private void linkStateMethods(@Nonnull final ComponentDescriptor descriptor) {
    final List<ExecutableElement> candidates = ProcessorUtil.getMethods(descriptor.getElement(), processingEnv.getTypeUtils()).stream().filter(m -> m.getModifiers().contains(Modifier.ABSTRACT)).filter(m -> null == ProcessorUtil.findAnnotationByType(descriptor.getElement(), Constants.PROP_ANNOTATION_CLASSNAME) && null == ProcessorUtil.findAnnotationByType(descriptor.getElement(), Constants.STATE_ANNOTATION_CLASSNAME)).collect(Collectors.toList());
    for (final ExecutableElement method : candidates) {
        final ExecutableType methodType = (ExecutableType) processingEnv.getTypeUtils().asMemberOf(descriptor.getDeclaredType(), method);
        if (method.getReturnType().getKind() == TypeKind.VOID && 1 == method.getParameters().size()) {
            final String stateName = ProcessorUtil.getPropertyMutatorName(method, ProcessorUtil.SENTINEL_NAME);
            final StateValueDescriptor stateValueNamed = descriptor.findStateValueNamed(stateName);
            if (null != stateValueNamed && !stateValueNamed.hasSetter()) {
                stateValueNamed.setSetter(method, methodType);
            }
        } else if (method.getReturnType().getKind() != TypeKind.VOID && 0 == method.getParameters().size()) {
            final String stateName = ProcessorUtil.getPropertyAccessorName(method, ProcessorUtil.SENTINEL_NAME);
            final StateValueDescriptor stateValueNamed = descriptor.findStateValueNamed(stateName);
            if (null != stateValueNamed && !stateValueNamed.hasGetter()) {
                stateValueNamed.setGetter(method, methodType);
            }
        }
    }
}
Also used : 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) ExecutableType(javax.lang.model.type.ExecutableType) ExecutableElement(javax.lang.model.element.ExecutableElement)

Example 49 with ExecutableType

use of javax.lang.model.type.ExecutableType in project react4j by react4j.

the class ReactProcessor method determineLifecycleMethods.

private void determineLifecycleMethods(@Nonnull final TypeElement typeElement, @Nonnull final ComponentDescriptor descriptor) {
    /*
     * Get the list of lifecycle methods that have been overridden by typeElement
     * a parent class, or by a default method method implemented by typeElement or
     * a parent class.
     */
    final Collection<ExecutableElement> lifecycleMethods = getComponentLifecycleMethods().values();
    final Elements elementUtils = processingEnv.getElementUtils();
    final Types typeUtils = processingEnv.getTypeUtils();
    final TypeElement componentType = elementUtils.getTypeElement(Constants.COMPONENT_CLASSNAME);
    final List<MethodDescriptor> overriddenLifecycleMethods = // Get all methods on type parent classes, and default methods from interfaces
    ProcessorUtil.getMethods(typeElement, processingEnv.getTypeUtils()).stream().filter(m -> lifecycleMethods.stream().anyMatch(l -> elementUtils.overrides(m, l, typeElement))).filter(m -> m.getEnclosingElement() != componentType).map(m -> new MethodDescriptor(m, (ExecutableType) typeUtils.asMemberOf(descriptor.getDeclaredType(), m))).collect(Collectors.toList());
    descriptor.setLifecycleMethods(overriddenLifecycleMethods);
}
Also used : 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) SupportedAnnotationTypes(javax.annotation.processing.SupportedAnnotationTypes) Types(javax.lang.model.util.Types) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Elements(javax.lang.model.util.Elements)

Example 50 with ExecutableType

use of javax.lang.model.type.ExecutableType in project react4j by react4j.

the class Generator method buildPropMethod.

private static MethodSpec.Builder buildPropMethod(@Nonnull final ComponentDescriptor descriptor, @Nonnull final PropDescriptor prop) {
    final ExecutableElement methodElement = prop.getMethod();
    final ExecutableType methodType = prop.getMethodType();
    final TypeMirror returnType = methodType.getReturnType();
    final MethodSpec.Builder method = MethodSpec.methodBuilder(methodElement.getSimpleName().toString()).returns(TypeName.get(returnType));
    ProcessorUtil.copyTypeParameters(methodType, method);
    ProcessorUtil.copyAccessModifiers(methodElement, method);
    ProcessorUtil.copyDocumentedAnnotations(methodElement, method);
    method.addAnnotation(Override.class);
    final String name = prop.getName();
    if (descriptor.isArezComponent()) {
        final AnnotationSpec.Builder annotation = AnnotationSpec.builder(OBSERVABLE_ANNOTATION_CLASSNAME).addMember("name", "$S", name).addMember("expectSetter", "false");
        method.addAnnotation(annotation.build());
    }
    final Element propType = prop.getPropType();
    if (null != propType && descriptor.isArezComponent() && ElementKind.CLASS == propType.getKind()) {
        if (null != ProcessorUtil.findAnnotationByType(propType, Constants.AREZ_COMPONENT_ANNOTATION_CLASSNAME)) {
            method.addAnnotation(AnnotationSpec.builder(AREZ_DEPENDENCY_CLASSNAME).build());
        }
    }
    final String convertMethodName = getConverter(returnType, methodElement, "Prop");
    final String key = "child".equals(name) ? "children" : name;
    if (null == ProcessorUtil.findAnnotationByType(methodElement, Constants.NONNULL_ANNOTATION_CLASSNAME)) {
        method.addStatement("return props().has( $S ) ? props().getAny( $S ).$N() : null", key, key, convertMethodName);
    } else {
        method.addStatement("return props().getAny( $S ).$N()", key, convertMethodName);
    }
    return method;
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) TypeMirror(javax.lang.model.type.TypeMirror) MethodSpec(com.squareup.javapoet.MethodSpec) ExecutableElement(javax.lang.model.element.ExecutableElement) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) AnnotationSpec(com.squareup.javapoet.AnnotationSpec)

Aggregations

ExecutableType (javax.lang.model.type.ExecutableType)83 ExecutableElement (javax.lang.model.element.ExecutableElement)64 DeclaredType (javax.lang.model.type.DeclaredType)47 TypeMirror (javax.lang.model.type.TypeMirror)45 TypeElement (javax.lang.model.element.TypeElement)44 Element (javax.lang.model.element.Element)33 VariableElement (javax.lang.model.element.VariableElement)33 Nonnull (javax.annotation.Nonnull)22 ArrayList (java.util.ArrayList)18 MethodSpec (com.squareup.javapoet.MethodSpec)15 HashMap (java.util.HashMap)15 Map (java.util.Map)15 AnnotationMirror (javax.lang.model.element.AnnotationMirror)15 TypeSpec (com.squareup.javapoet.TypeSpec)14 HashSet (java.util.HashSet)14 TypeKind (javax.lang.model.type.TypeKind)14 IOException (java.io.IOException)13 Nullable (javax.annotation.Nullable)13 PackageElement (javax.lang.model.element.PackageElement)13 List (java.util.List)12