in litho-processor/src/main/java/com/facebook/litho/specmodels/generator/DelegateMethodGenerator.java [249:438]
public static CodeBlock getDelegationCode(
SpecModel specModel,
SpecMethodModel<DelegateMethod, Void> delegateMethod,
DelegateMethodDescription methodDescription,
@Nullable String contextParamName,
@Nullable String interStagePropsParamName,
EnumSet<RunMode> runMode) {
final CodeBlock.Builder acquireStatements = CodeBlock.builder();
final CodeBlock.Builder releaseStatements = CodeBlock.builder();
final List<ParamTypeAndName> delegationParams =
new ArrayList<>(delegateMethod.methodParams.size());
final ImmutableList<TypeName> allowedParamTypes =
methodDescription.allowedDelegateMethodArguments();
// If null, find the first spec context from the delegate methods arguments.
if (contextParamName == null) {
contextParamName = getContextParamName(specModel, delegateMethod, methodDescription);
}
// Create a local variable for interstage props if they created or used.
if (ComponentBodyGenerator.requiresInterStatePropContainer(
delegateMethod.methodParams, methodDescription.optionalParameterTypes)) {
acquireStatements.addStatement(
"$L $L = $L",
ClassNames.INTER_STAGE_PROPS_CONTAINER,
ComponentBodyGenerator.LOCAL_INTER_STAGE_PROPS_CONTAINER_NAME,
interStagePropsParamName != null ? interStagePropsParamName : "null");
}
final boolean requiresState =
(methodDescription.createsState && !specModel.getStateValues().isEmpty())
|| delegateMethod.methodParams.stream().anyMatch(PREDICATE_NEEDS_STATE);
if (requiresState && contextParamName != null) {
acquireStatements.addStatement(
"$L $L = $L",
StateContainerGenerator.getStateContainerClassName(specModel),
LOCAL_STATE_CONTAINER_NAME,
STATE_CONTAINER_IMPL_GETTER + "(" + contextParamName + ")");
}
final Queue<TypeName> remainingAllowedTypes = new LinkedList<>(allowedParamTypes);
int numberOfAllowedArgsUsed = 0;
for (int i = 0, size = delegateMethod.methodParams.size(); i < size; i++) {
final MethodParamModel methodParamModel = delegateMethod.methodParams.get(i);
final boolean usesAllowedType =
isAllowedTypeAndConsume(methodParamModel, remainingAllowedTypes);
// Add delegate param if param type is allowed
if (usesAllowedType) {
numberOfAllowedArgsUsed++;
delegationParams.add(
ParamTypeAndName.create(methodParamModel.getTypeName(), methodParamModel.getName()));
} else if (i < numberOfAllowedArgsUsed + methodDescription.optionalParameters.size()
&& shouldIncludeOptionalParameter(
methodParamModel,
methodDescription.optionalParameters.get(i - numberOfAllowedArgsUsed))) {
final MethodParamModel extraDefinedParam =
methodDescription.optionalParameters.get(i - numberOfAllowedArgsUsed);
delegationParams.add(
ParamTypeAndName.create(extraDefinedParam.getTypeName(), extraDefinedParam.getName()));
} else if (methodParamModel instanceof DiffPropModel
|| methodParamModel instanceof DiffStateParamModel) {
if (specModel instanceof HasPureRender
&& (methodParamModel instanceof StateParamModel
|| SpecModelUtils.getStateValueWithName(specModel, methodParamModel.getName())
!= null)) {
final String stateContainerClassNameWithTypeVars =
StateGenerator.getStateContainerClassNameWithTypeVars(specModel);
acquireStatements.addStatement(
"$T $L = new $T(_prevImpl == null ? null : (($L) _prevStateContainer).$L, "
+ "_nextImpl == null ? null : (($L) _nextStateContainer).$L)",
methodParamModel.getTypeName(),
methodParamModel.getName(),
methodParamModel.getTypeName(),
stateContainerClassNameWithTypeVars,
methodParamModel.getName(),
stateContainerClassNameWithTypeVars,
methodParamModel.getName());
} else {
acquireStatements.addStatement(
// Diff<type> name = new Diff<type>(...)
"$T $L = new $T(_prevImpl == null ? null : _prevImpl.$L, "
+ "_nextImpl == null ? null : _nextImpl.$L)",
methodParamModel.getTypeName(),
methodParamModel.getName(),
methodParamModel.getTypeName(),
ComponentBodyGenerator.getImplAccessor(
methodDescription.name, specModel, methodParamModel, "_prevScopedContext"),
ComponentBodyGenerator.getImplAccessor(
methodDescription.name, specModel, methodParamModel, "_nextScopedContext"));
}
delegationParams.add(
ParamTypeAndName.create(methodParamModel.getTypeName(), methodParamModel.getName()));
} else if (isOutputType(methodParamModel.getTypeName())) {
String localOutputName = methodParamModel.getName() + "Tmp";
acquireStatements.add(
"$T $L = new Output<>();\n", methodParamModel.getTypeName(), localOutputName);
delegationParams.add(
ParamTypeAndName.create(methodParamModel.getTypeName(), localOutputName));
final boolean isPropOutput = SpecModelUtils.isPropOutput(specModel, methodParamModel);
if (isPropOutput) {
releaseStatements.beginControlFlow("if ($L.get() != null)", localOutputName);
}
releaseStatements.addStatement(
"$L = $L.get()",
getImplAccessor(specModel, methodDescription, methodParamModel, contextParamName),
localOutputName);
if (isPropOutput) {
releaseStatements.endControlFlow();
}
} else if (isStateValueType(methodParamModel.getTypeName())) {
acquireStatements.add(
"$T $L = new StateValue<>();\n",
methodParamModel.getTypeName(),
methodParamModel.getName());
delegationParams.add(
ParamTypeAndName.create(methodParamModel.getTypeName(), methodParamModel.getName()));
if (delegateMethod.name.toString().equals(LIFECYCLE_CREATE_INITIAL_STATE)) {
releaseStatements.beginControlFlow("if ($L.get() != null)", methodParamModel.getName());
}
releaseStatements.addStatement(
"$L = $L.get()",
getImplAccessorFromContainer(
methodDescription.name,
specModel,
methodParamModel,
contextParamName,
LOCAL_STATE_CONTAINER_NAME),
methodParamModel.getName());
if (delegateMethod.name.toString().equals(LIFECYCLE_CREATE_INITIAL_STATE)) {
releaseStatements.endControlFlow();
}
} else if (methodParamModel instanceof RenderDataDiffModel) {
final String diffName = "_" + methodParamModel.getName() + "Diff";
CodeBlock block =
CodeBlock.builder()
// Diff<type> name = new Diff<type>(...)
.add(
"$T $L = new $T(\n",
methodParamModel.getTypeName(),
diffName,
methodParamModel.getTypeName())
.indent()
.add(
"$L == null ? null : $L.$L,\n",
PREVIOUS_RENDER_DATA_FIELD_NAME,
PREVIOUS_RENDER_DATA_FIELD_NAME,
methodParamModel.getName())
.add(
"$L);\n",
getImplAccessor(
methodDescription.name, specModel, methodParamModel, contextParamName))
.unindent()
.build();
acquireStatements.add(block);
delegationParams.add(ParamTypeAndName.create(methodParamModel.getTypeName(), diffName));
} else {
delegationParams.add(
ParamTypeAndName.create(
methodParamModel.getTypeName(),
getImplAccessorFromContainer(
methodDescription.name,
specModel,
methodParamModel,
contextParamName,
LOCAL_STATE_CONTAINER_NAME)));
}
}
return CodeBlock.builder()
.add(acquireStatements.build())
.add(
getDelegationMethod(
specModel,
delegateMethod.name,
methodDescription.returnType,
ImmutableList.copyOf(delegationParams)))
.add(releaseStatements.build())
.build();
}