Search in sources :

Example 56 with ExecutableType

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

the class BuilderGenerator method buildBuilderStepInterface.

@Nonnull
private static TypeSpec buildBuilderStepInterface(@Nonnull final ProcessingEnvironment processingEnv, @Nonnull final ViewDescriptor descriptor, @Nonnull final Step step) {
    final int stepIndex = step.getIndex();
    final TypeSpec.Builder builder = TypeSpec.interfaceBuilder("Step" + stepIndex);
    builder.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
    builder.addTypeVariables(GeneratorUtil.getTypeArgumentsAsNames(descriptor.getDeclaredType()));
    if (!descriptor.getDeclaredType().getTypeArguments().isEmpty()) {
        builder.addAnnotation(SuppressWarningsUtil.suppressWarningsAnnotation("unused"));
    }
    for (final StepMethod stepMethod : step.getMethods()) {
        final StepMethodType stepMethodType = stepMethod.getStepMethodType();
        // Magically handle the step method named build
        if (stepMethod.isBuildIntrinsic()) {
            builder.addMethod(buildStepInterfaceMethod(descriptor, "build", step, stepMethodType, m -> {
            }).build());
        } else {
            builder.addMethod(buildStepInterfaceMethod(descriptor, stepMethod.getName(), step, stepMethodType, m -> {
                final ExecutableType inputMethodType = stepMethod.getMethodType();
                if (null != inputMethodType) {
                    GeneratorUtil.copyTypeParameters(inputMethodType, m);
                }
                if (stepMethod.isChildrenIntrinsic()) {
                    m.varargs();
                }
                final TypeName type = stepMethod.getType();
                if (type instanceof ArrayTypeName) {
                    m.varargs();
                }
                final ParameterSpec.Builder parameter = ParameterSpec.builder(type, stepMethod.getName());
                final ExecutableElement inputMethod = stepMethod.getMethod();
                if (null != inputMethod) {
                    GeneratorUtil.copyWhitelistedAnnotations(inputMethod, parameter);
                    final ExecutableType methodType = stepMethod.getMethodType();
                    assert null != methodType;
                    SuppressWarningsUtil.addSuppressWarningsIfRequired(processingEnv, parameter, methodType.getReturnType());
                } else if (stepMethod.isChildrenStreamIntrinsic()) {
                    parameter.addAnnotation(GeneratorUtil.NONNULL_CLASSNAME);
                }
                m.addParameter(parameter.build());
            }).build());
        }
    }
    return builder.build();
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) WildcardTypeName(com.squareup.javapoet.WildcardTypeName) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) ArrayTypeName(com.squareup.javapoet.ArrayTypeName) ArrayTypeName(com.squareup.javapoet.ArrayTypeName) ParameterSpec(com.squareup.javapoet.ParameterSpec) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeSpec(com.squareup.javapoet.TypeSpec) Nonnull(javax.annotation.Nonnull)

Example 57 with ExecutableType

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

the class React4jProcessor method determinePublishMethods.

private void determinePublishMethods(@Nonnull final TypeElement typeElement, @Nonnull final ViewDescriptor descriptor) {
    final List<PublishDescriptor> descriptors = new ArrayList<>();
    for (final ExecutableElement method : getMethods(typeElement)) {
        final AnnotationMirror annotation = AnnotationsUtil.findAnnotationByType(method, Constants.PUBLISH_CLASSNAME);
        if (null != annotation) {
            MemberChecks.mustBeSubclassCallable(typeElement, Constants.VIEW_CLASSNAME, Constants.PUBLISH_CLASSNAME, method);
            MemberChecks.mustNotHaveAnyParameters(Constants.PUBLISH_CLASSNAME, method);
            MemberChecks.mustNotHaveAnyTypeParameters(Constants.PUBLISH_CLASSNAME, method);
            MemberChecks.mustReturnAValue(Constants.PUBLISH_CLASSNAME, method);
            MemberChecks.mustNotThrowAnyExceptions(Constants.PUBLISH_CLASSNAME, method);
            final String qualifier = AnnotationsUtil.getAnnotationValueValue(annotation, "qualifier");
            final ExecutableType methodType = resolveMethodType(descriptor, method);
            if (TypeKind.TYPEVAR == methodType.getReturnType().getKind()) {
                throw new ProcessorException(MemberChecks.mustNot(Constants.PUBLISH_CLASSNAME, "return a type variable"), method);
            }
            descriptors.add(new PublishDescriptor(qualifier, method, methodType));
        }
    }
    descriptor.setPublishDescriptors(descriptors);
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) AnnotationMirror(javax.lang.model.element.AnnotationMirror) ProcessorException(org.realityforge.proton.ProcessorException) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList)

Example 58 with ExecutableType

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

the class BuilderGenerator method buildBuilderStepImpl.

@Nonnull
private static MethodSpec buildBuilderStepImpl(@Nonnull final ProcessingEnvironment processingEnv, @Nonnull final ViewDescriptor descriptor, @Nonnull final Step step, @Nonnull final StepMethod stepMethod) {
    final MethodSpec.Builder method = MethodSpec.methodBuilder(stepMethod.getName());
    method.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
    method.addAnnotation(Override.class);
    method.addAnnotation(GeneratorUtil.NONNULL_CLASSNAME);
    final InputDescriptor input = stepMethod.getInput();
    final ExecutableType inputMethodType = stepMethod.getMethodType();
    if (null != inputMethodType) {
        GeneratorUtil.copyTypeParameters(inputMethodType, method);
    }
    final TypeName type = stepMethod.getType();
    final ParameterSpec.Builder parameter = ParameterSpec.builder(type, stepMethod.getName(), Modifier.FINAL);
    if (type instanceof ArrayTypeName) {
        method.varargs();
    }
    final ExecutableElement inputMethod = stepMethod.getMethod();
    if (null != inputMethod) {
        GeneratorUtil.copyWhitelistedAnnotations(inputMethod, parameter);
        final ExecutableType methodType = stepMethod.getMethodType();
        assert null != methodType;
        SuppressWarningsUtil.addSuppressWarningsIfRequired(processingEnv, parameter, methodType.getReturnType());
    } else if (stepMethod.isChildrenStreamIntrinsic()) {
        parameter.addAnnotation(GeneratorUtil.NONNULL_CLASSNAME);
    }
    method.addParameter(parameter.build());
    if (null != input && input.isImmutable() && 1 == descriptor.syntheticKeyParts()) {
        final ImmutableInputKeyStrategy strategy = input.getImmutableInputKeyStrategy();
        if (ImmutableInputKeyStrategy.KEYED == strategy) {
            method.addStatement("_element.setKey( $T.getKey( $N ) + " + "( $T.enableViewNames() ? $S : $T.class.getName() ) )", KEYED_CLASSNAME, stepMethod.getName(), REACT_CLASSNAME, descriptor.keySuffix(), descriptor.getClassName());
        } else if (ImmutableInputKeyStrategy.IS_STRING == strategy || ImmutableInputKeyStrategy.TO_STRING == strategy || ImmutableInputKeyStrategy.ENUM == strategy) {
            method.addStatement("_element.setKey( $N + ( $T.enableViewNames() ? $S : $T.class.getName() ) )", stepMethod.getName(), REACT_CLASSNAME, descriptor.keySuffix(), descriptor.getClassName());
        } else if (ImmutableInputKeyStrategy.DYNAMIC == strategy) {
            method.addStatement("_element.setKey( ( $N instanceof $T ? $T.getKey( $N ) : " + "$N instanceof $T ? $T.<$T>getArezId( $N ) : $T.valueOf( $N ) ) + " + "( $T.enableViewNames() ? $S : $T.class.getName() ) )", stepMethod.getName(), KEYED_CLASSNAME, KEYED_CLASSNAME, stepMethod.getName(), stepMethod.getName(), IDENTIFIABLE_CLASSNAME, IDENTIFIABLE_CLASSNAME, Object.class, stepMethod.getName(), String.class, stepMethod.getName(), REACT_CLASSNAME, descriptor.keySuffix(), descriptor.getClassName());
        } else {
            assert ImmutableInputKeyStrategy.AREZ_IDENTIFIABLE == strategy;
            method.addStatement("_element.setKey( $T.<Object>getArezId( $N ) + " + "( $T.enableViewNames() ? $S : $T.class.getName() ) )", IDENTIFIABLE_CLASSNAME, stepMethod.getName(), REACT_CLASSNAME, descriptor.keySuffix(), descriptor.getClassName());
        }
    }
    if (stepMethod.isChildrenIntrinsic()) {
        method.varargs();
        assert null != input;
        method.addStatement("_element.input( $T.Inputs.$N, $T.of( $N ) )", descriptor.getEnhancedClassName(), input.getConstantName(), JS_ARRAY_CLASSNAME, stepMethod.getName());
    } else if (stepMethod.isChildrenStreamIntrinsic()) {
        method.addStatement("children( $N.toArray( $T[]::new ) )", stepMethod.getName(), REACT_NODE_CLASSNAME);
    } else if (stepMethod.isChildIntrinsic()) {
        assert null != inputMethod;
        assert null != input;
        if (AnnotationsUtil.hasNonnullAnnotation(inputMethod)) {
            method.addStatement("_element.input( $T.Inputs.$N, $T.of( $T.requireNonNull( $N ) ) )", descriptor.getEnhancedClassName(), input.getConstantName(), JS_ARRAY_CLASSNAME, Objects.class, stepMethod.getName());
        } else {
            method.addStatement("_element.input( $T.Inputs.$N, $T.of( $N ) )", descriptor.getEnhancedClassName(), input.getConstantName(), JS_ARRAY_CLASSNAME, stepMethod.getName());
        }
    } else {
        if ((null != inputMethod && AnnotationsUtil.hasNonnullAnnotation(inputMethod)) && !type.isPrimitive()) {
            method.addStatement("$T.requireNonNull( $N )", Objects.class, stepMethod.getName());
        }
        assert null != input;
        method.addStatement("_element.input( $T.Inputs.$N, $N )", descriptor.getEnhancedClassName(), input.getConstantName(), stepMethod.getName());
    }
    if (StepMethodType.TERMINATE == stepMethod.getStepMethodType()) {
        method.addStatement("return build()");
    } else {
        method.addStatement("return this");
    }
    configureStepMethodReturns(descriptor, method, step, stepMethod.getStepMethodType());
    return method.build();
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) WildcardTypeName(com.squareup.javapoet.WildcardTypeName) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) ArrayTypeName(com.squareup.javapoet.ArrayTypeName) MethodSpec(com.squareup.javapoet.MethodSpec) ParameterSpec(com.squareup.javapoet.ParameterSpec) ArrayTypeName(com.squareup.javapoet.ArrayTypeName) ExecutableElement(javax.lang.model.element.ExecutableElement) Nonnull(javax.annotation.Nonnull)

Example 59 with ExecutableType

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

the class ViewGenerator method buildInputMethod.

@Nonnull
private static MethodSpec.Builder buildInputMethod(@Nonnull final InputDescriptor input) {
    final ExecutableElement methodElement = input.getMethod();
    final ExecutableType methodType = input.getMethodType();
    final TypeMirror returnType = methodType.getReturnType();
    final MethodSpec.Builder method = MethodSpec.methodBuilder(methodElement.getSimpleName().toString()).returns(TypeName.get(returnType));
    GeneratorUtil.copyTypeParameters(methodType, method);
    GeneratorUtil.copyAccessModifiers(methodElement, method);
    GeneratorUtil.copyWhitelistedAnnotations(methodElement, method);
    method.addAnnotation(Override.class);
    if (input.isObservable()) {
        final AnnotationSpec.Builder annotation = AnnotationSpec.builder(OBSERVABLE_ANNOTATION_CLASSNAME).addMember("name", "$S", input.getName()).addMember("expectSetter", "false").addMember("readOutsideTransaction", "$T.ENABLE", AREZ_FEATURE_CLASSNAME);
        method.addAnnotation(annotation.build());
    }
    if (input.needsMutableInputAccessedInPostConstructInvariant()) {
        final CodeBlock.Builder block = CodeBlock.builder();
        block.beginControlFlow("if ( $T.shouldCheckInvariants() )", REACT_CLASSNAME);
        block.addStatement("$T.apiInvariant( () -> $N(), " + "() -> \"The view '\" + this + \"' accessed the input named '" + input.getName() + "' before the view is ready (possibly in a @PostConstruct annotated method?) and " + "does not have a @OnInputChange annotated method to cover the input and reflect changes " + "of the input onto the view. This is considered a likely bug and the @Input should be " + "made immutable or an @OnInputChange method added to cover the input. " + MemberChecks.suppressedBy(Constants.WARNING_MUTABLE_INPUT_ACCESSED_IN_POST_CONSTRUCT, Constants.SUPPRESS_REACT4J_WARNINGS_CLASSNAME).replace("\"", "\\\"") + " to the @Input annotated method.\" )", GUARDS_CLASSNAME, IS_READY_METHOD);
        block.endControlFlow();
        method.addCode(block.build());
    }
    if (input.isImmutable()) {
        method.addStatement("return $N", FRAMEWORK_INTERNAL_IMMUTABLE_INPUT_PREFIX + input.getName());
    } else {
        final String convertMethodName = getConverter(returnType, methodElement);
        final TypeKind resultKind = methodElement.getReturnType().getKind();
        if (!resultKind.isPrimitive() && !AnnotationsUtil.hasNonnullAnnotation(methodElement)) {
            final CodeBlock.Builder block = CodeBlock.builder();
            block.beginControlFlow("if ( $T.shouldCheckInvariants() )", REACT_CLASSNAME);
            block.addStatement("return null != $N.inputs().getAsAny( Inputs.$N ) ? " + "$N.inputs().getAsAny( Inputs.$N ).$N() : null", NATIVE_VIEW_FIELD, input.getConstantName(), NATIVE_VIEW_FIELD, input.getConstantName(), convertMethodName);
            block.nextControlFlow("else");
            block.addStatement("return $T.uncheckedCast( $N.inputs().getAsAny( Inputs.$N ) )", JS_CLASSNAME, NATIVE_VIEW_FIELD, input.getConstantName());
            block.endControlFlow();
            method.addCode(block.build());
        } else {
            method.addStatement("return $N.inputs().getAsAny( Inputs.$N ).$N()", NATIVE_VIEW_FIELD, input.getConstantName(), 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) CodeBlock(com.squareup.javapoet.CodeBlock) TypeKind(javax.lang.model.type.TypeKind) AnnotationSpec(com.squareup.javapoet.AnnotationSpec) Nonnull(javax.annotation.Nonnull)

Example 60 with ExecutableType

use of javax.lang.model.type.ExecutableType in project auto by google.

the class MoreTypes method asMemberOf.

/**
 * Resolves a {@link VariableElement} parameter to a method or constructor based on the given
 * container, or a member of a class. For parameters to a method or constructor, the variable's
 * enclosing element must be a supertype of the container type. For example, given a
 * {@code container} of type {@code Set<String>}, and a variable corresponding to the {@code E e}
 * parameter in the {@code Set.add(E e)} method, this will return a TypeMirror for {@code String}.
 */
public static TypeMirror asMemberOf(Types types, DeclaredType container, VariableElement variable) {
    if (variable.getKind().equals(ElementKind.PARAMETER)) {
        ExecutableElement methodOrConstructor = MoreElements.asExecutable(variable.getEnclosingElement());
        ExecutableType resolvedMethodOrConstructor = MoreTypes.asExecutable(types.asMemberOf(container, methodOrConstructor));
        List<? extends VariableElement> parameters = methodOrConstructor.getParameters();
        List<? extends TypeMirror> parameterTypes = resolvedMethodOrConstructor.getParameterTypes();
        checkState(parameters.size() == parameterTypes.size());
        for (int i = 0; i < parameters.size(); i++) {
            // types.asMemberOf on variables of methods.
            if (parameters.get(i).equals(variable)) {
                return parameterTypes.get(i);
            }
        }
        throw new IllegalStateException("Could not find variable: " + variable);
    } else {
        return types.asMemberOf(container, variable);
    }
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) ExecutableElement(javax.lang.model.element.ExecutableElement)

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