From 86ecedbef31949b94e65b720ccb9f9a7cca5f645 Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Mon, 26 Feb 2018 08:21:50 -0800 Subject: [PATCH] Refactor event case generation 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 --- .../generator/EventCaseGeneratorTest.java | 58 +++++++++ .../generator/EventCaseGenerator.java | 111 ++++++++++++++++++ .../specmodels/generator/EventGenerator.java | 54 +-------- 3 files changed, 174 insertions(+), 49 deletions(-) create mode 100644 litho-it/src/test/java/com/facebook/litho/specmodels/generator/EventCaseGeneratorTest.java create mode 100644 litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventCaseGenerator.java diff --git a/litho-it/src/test/java/com/facebook/litho/specmodels/generator/EventCaseGeneratorTest.java b/litho-it/src/test/java/com/facebook/litho/specmodels/generator/EventCaseGeneratorTest.java new file mode 100644 index 00000000000..35afc449f28 --- /dev/null +++ b/litho-it/src/test/java/com/facebook/litho/specmodels/generator/EventCaseGeneratorTest.java @@ -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"); + } +} diff --git a/litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventCaseGenerator.java b/litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventCaseGenerator.java new file mode 100644 index 00000000000..ef8c9cd1d59 --- /dev/null +++ b/litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventCaseGenerator.java @@ -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> + mEventMethodModels; + + EventCaseGenerator( + ClassName contextClass, + ImmutableList> eventMethodModels) { + mContextClass = contextClass; + mEventMethodModels = eventMethodModels; + } + + public void writeTo(MethodSpec.Builder methodBuilder) { + mEventMethodModels.forEach(e -> writeCase(methodBuilder, e)); + } + + private void writeCase( + MethodSpec.Builder methodBuilder, + SpecMethodModel 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> mEventMethodModels; + + private Builder() {} + + public Builder contextClass(ClassName contextClass) { + mContextClass = contextClass; + return this; + } + + public Builder eventMethodModels( + ImmutableList> eventMethodModels) { + mEventMethodModels = eventMethodModels; + return this; + } + + public void writeTo(MethodSpec.Builder methodBuilder) { + new EventCaseGenerator(mContextClass, mEventMethodModels).writeTo(methodBuilder); + } + } +} diff --git a/litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventGenerator.java b/litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventGenerator.java index 92b09845e4c..becd41d5f84 100644 --- a/litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventGenerator.java +++ b/litho-processor/src/main/java/com/facebook/litho/specmodels/generator/EventGenerator.java @@ -248,55 +248,10 @@ static MethodSpec generateDispatchOnEvent(SpecModel specModel) { methodBuilder.addStatement("int id = eventHandler.id"); methodBuilder.beginControlFlow("switch ($L)", "id"); - for (SpecMethodModel 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() @@ -353,4 +308,5 @@ static MethodSpec generateEventHandlerFactory( return builder.build(); } + }