Skip to content

Commit

Permalink
Refactor event case generation
Browse files Browse the repository at this point in the history
Summary:
I'm going to add a lot of additional logic to the case generation for error
boundaries, so I want to make sure the structure can accomodate for this.

I've moved the actual case generation to a separate class with a builder that
can be tested in isolation.

Reviewed By: marco-cova

Differential Revision: D7084490

fbshipit-source-id: 2a8b0420a077bc9ade1eca543b4c9eb4758dd217
  • Loading branch information
passy authored and facebook-github-bot committed Feb 26, 2018
1 parent df0d0a9 commit 86ecedb
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

package com.facebook.litho.specmodels.generator;

import static org.assertj.core.api.Java6Assertions.assertThat;

import com.facebook.litho.specmodels.internal.ImmutableList;
import com.facebook.litho.specmodels.model.ClassNames;
import com.facebook.litho.specmodels.model.EventDeclarationModel;
import com.facebook.litho.specmodels.model.SpecMethodModel;
import com.facebook.litho.specmodels.model.TypeSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import org.junit.Test;

/** Tests {@link EventCaseGenerator} */
public class EventCaseGeneratorTest {
@Test
public void testBasicGeneratorCase() {
final MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("method");
final EventDeclarationModel model =
new EventDeclarationModel(ClassName.OBJECT, TypeName.VOID, ImmutableList.of(), null);

EventCaseGenerator.builder()
.contextClass(ClassNames.COMPONENT_CONTEXT)
.eventMethodModels(
ImmutableList.of(
new SpecMethodModel<>(
ImmutableList.of(),
ImmutableList.of(),
"event",
new TypeSpec(TypeName.VOID),
ImmutableList.of(),
ImmutableList.of(),
null,
model)))
.writeTo(methodBuilder);

assertThat(methodBuilder.build().toString())
.isEqualTo(
"void method() {\n"
+ " case 96891546: {\n"
+ " java.lang.Object _event = (java.lang.Object) eventState;\n"
+ " event(\n"
+ " eventHandler.mHasEventDispatcher);\n"
+ " return null;\n"
+ " }\n"
+ "}\n");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.litho.specmodels.generator;

import com.facebook.litho.annotations.FromEvent;
import com.facebook.litho.annotations.Param;
import com.facebook.litho.specmodels.internal.ImmutableList;
import com.facebook.litho.specmodels.model.EventDeclarationModel;
import com.facebook.litho.specmodels.model.EventMethod;
import com.facebook.litho.specmodels.model.MethodParamModel;
import com.facebook.litho.specmodels.model.MethodParamModelUtils;
import com.facebook.litho.specmodels.model.SpecMethodModel;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;

/** Generator for the cases within the event handler switch clause. */
class EventCaseGenerator {
private final ClassName mContextClass;
private final ImmutableList<SpecMethodModel<EventMethod, EventDeclarationModel>>
mEventMethodModels;

EventCaseGenerator(
ClassName contextClass,
ImmutableList<SpecMethodModel<EventMethod, EventDeclarationModel>> eventMethodModels) {
mContextClass = contextClass;
mEventMethodModels = eventMethodModels;
}

public void writeTo(MethodSpec.Builder methodBuilder) {
mEventMethodModels.forEach(e -> writeCase(methodBuilder, e));
}

private void writeCase(
MethodSpec.Builder methodBuilder,
SpecMethodModel<EventMethod, EventDeclarationModel> eventMethodModel) {
methodBuilder.beginControlFlow("case $L:", eventMethodModel.name.toString().hashCode());

final String eventVariableName = "_event";

methodBuilder.addStatement(
"$T $L = ($T) $L",
eventMethodModel.typeModel.name,
eventVariableName,
eventMethodModel.typeModel.name,
"eventState");

final CodeBlock.Builder eventHandlerParams =
CodeBlock.builder().indent().add("\n$L", "eventHandler.mHasEventDispatcher");

int paramIndex = 0;
for (MethodParamModel methodParamModel : eventMethodModel.methodParams) {
if (MethodParamModelUtils.isAnnotatedWith(methodParamModel, FromEvent.class)) {
eventHandlerParams.add(
",\n($T) $L.$L",
methodParamModel.getTypeName(),
eventVariableName,
methodParamModel.getName());
} else if (MethodParamModelUtils.isAnnotatedWith(methodParamModel, Param.class)
|| methodParamModel.getTypeName().equals(mContextClass)) {
eventHandlerParams.add(
",\n($T) eventHandler.params[$L]", methodParamModel.getTypeName(), paramIndex++);
}
}

eventHandlerParams.unindent();

if (!eventMethodModel.returnType.equals(TypeName.VOID)) {
methodBuilder.addStatement(
"return $L($L)", eventMethodModel.name, eventHandlerParams.build());
} else {
methodBuilder.addStatement("$L($L)", eventMethodModel.name, eventHandlerParams.build());
methodBuilder.addStatement("return null");
}

methodBuilder.endControlFlow();
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private ClassName mContextClass;
private ImmutableList<SpecMethodModel<EventMethod, EventDeclarationModel>> mEventMethodModels;

private Builder() {}

public Builder contextClass(ClassName contextClass) {
mContextClass = contextClass;
return this;
}

public Builder eventMethodModels(
ImmutableList<SpecMethodModel<EventMethod, EventDeclarationModel>> eventMethodModels) {
mEventMethodModels = eventMethodModels;
return this;
}

public void writeTo(MethodSpec.Builder methodBuilder) {
new EventCaseGenerator(mContextClass, mEventMethodModels).writeTo(methodBuilder);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,55 +248,10 @@ static MethodSpec generateDispatchOnEvent(SpecModel specModel) {
methodBuilder.addStatement("int id = eventHandler.id");
methodBuilder.beginControlFlow("switch ($L)", "id");

for (SpecMethodModel<EventMethod, EventDeclarationModel> eventMethodModel :
specModel.getEventMethods()) {
methodBuilder.beginControlFlow("case $L:", eventMethodModel.name.toString().hashCode());

final String eventVariableName = "_event";

methodBuilder.addStatement(
"$T $L = ($T) $L",
eventMethodModel.typeModel.name,
eventVariableName,
eventMethodModel.typeModel.name,
"eventState");

final CodeBlock.Builder eventHandlerParams = CodeBlock.builder()
.indent()
.add("\n$L", "eventHandler.mHasEventDispatcher");

int paramIndex = 0;
for (MethodParamModel methodParamModel : eventMethodModel.methodParams) {
if (MethodParamModelUtils.isAnnotatedWith(methodParamModel, FromEvent.class)) {
eventHandlerParams.add(
",\n($T) $L.$L",
methodParamModel.getTypeName(),
eventVariableName,
methodParamModel.getName());
} else if (MethodParamModelUtils.isAnnotatedWith(methodParamModel, Param.class) ||
methodParamModel.getTypeName().equals(specModel.getContextClass())) {
eventHandlerParams.add(
",\n($T) eventHandler.params[$L]", methodParamModel.getTypeName(), paramIndex++);
}
}

eventHandlerParams.unindent();

if (!eventMethodModel.returnType.equals(TypeName.VOID)) {
methodBuilder.addStatement(
"return $L($L)",
eventMethodModel.name,
eventHandlerParams.build());
} else {
methodBuilder.addStatement(
"$L($L)",
eventMethodModel.name,
eventHandlerParams.build());
methodBuilder.addStatement("return null");
}

methodBuilder.endControlFlow();
}
EventCaseGenerator.builder()
.contextClass(specModel.getContextClass())
.eventMethodModels(specModel.getEventMethods())
.writeTo(methodBuilder);

return methodBuilder.addStatement("default:\nreturn null")
.endControlFlow()
Expand Down Expand Up @@ -353,4 +308,5 @@ static MethodSpec generateEventHandlerFactory(

return builder.build();
}

}

0 comments on commit 86ecedb

Please sign in to comment.