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();
}
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);
}
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();
}
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;
}
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);
}
}
Aggregations