From a24a9b9946bbead2ba6db096296fc4c2d3676410 Mon Sep 17 00:00:00 2001 From: Eli White Date: Wed, 24 Jul 2019 16:45:36 -0700 Subject: [PATCH] Back out "Back out D16434402, D16434634" Summary: Reverting the revert and fixing the snapshot tests Reviewed By: JoshuaGross Differential Revision: D16467242 fbshipit-source-id: 23ed4122da226ea815d3766098da4400e7ad9442 --- .../components/GeneratePropsJavaDelegate.js | 94 ++++++++++++++++++- .../components/GeneratePropsJavaInterface.js | 17 ++-- .../src/generators/components/JavaHelpers.js | 16 +++- .../components/__test_fixtures__/fixtures.js | 8 ++ .../GeneratePropsJavaDelegate-test.js.snap | 20 ++++ .../GeneratePropsJavaInterface-test.js.snap | 1 + .../GenerateViewConfigJs-test.js.snap | 8 ++ 7 files changed, 145 insertions(+), 19 deletions(-) diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js index 95aaf1c294a..955686b8b87 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js @@ -11,6 +11,7 @@ 'use strict'; import type { + CommandTypeShape, ComponentShape, PropTypeShape, SchemaType, @@ -26,10 +27,20 @@ package com.facebook.react.viewmanagers; ::_IMPORTS_:: public class ::_CLASSNAME_:: { + ::_METHODS_:: +} +`; + +const propSetterTemplate = ` public void setProperty(::_INTERFACE_CLASSNAME_:: viewManager, T view, String propName, Object value) { ::_PROP_CASES_:: } -} +`; + +const commandsTemplate = ` + public void receiveCommand(::_INTERFACE_CLASSNAME_:: viewManager, T view, String commandName, ReadableArray args) { + ::_COMMAND_CASES_:: + } `; function getJavaValueForProp( @@ -105,6 +116,51 @@ function generatePropCasesString( }`; } +function getCommandArgJavaType(param) { + switch (param.typeAnnotation.type) { + case 'BooleanTypeAnnotation': + return 'getBoolean'; + case 'Int32TypeAnnotation': + return 'getInt'; + default: + (param.typeAnnotation.type: empty); + throw new Error('Receieved invalid typeAnnotation'); + } +} + +function getCommandArguments(command: CommandTypeShape): string { + return [ + 'view', + ...command.typeAnnotation.params.map((param, index) => { + const commandArgJavaType = getCommandArgJavaType(param); + + return `args.${commandArgJavaType}(${index})`; + }), + ].join(', '); +} + +function generateCommandCasesString( + component: ComponentShape, + componentName: string, +) { + if (component.commands.length === 0) { + return null; + } + + const commandMethods = component.commands + .map(command => { + return `case "${command.name}": + viewManager.${toSafeJavaString( + command.name, + false, + )}(${getCommandArguments(command)}); + break;`; + }) + .join('\n' + ' '); + + return commandMethods; +} + function getClassExtendString(component): string { const extendString = component.extendsProps .map(extendProps => { @@ -127,6 +183,28 @@ function getClassExtendString(component): string { return extendString; } +function getDelegateImports(component) { + const imports = getImports(component); + // The delegate needs ReadableArray for commands always. + // The interface doesn't always need it + if (component.commands.length > 0) { + imports.add('import com.facebook.react.bridge.ReadableArray;'); + } + + return imports; +} + +function generateMethods(propsString, commandsString): string { + return [ + propSetterTemplate.trim().replace('::_PROP_CASES_::', propsString), + commandsString != null + ? commandsTemplate.trim().replace('::_COMMAND_CASES_::', commandsString) + : '', + ] + .join('\n\n ') + .trimRight(); +} + module.exports = { generate(libraryName: string, schema: SchemaType): FilesOutput { const files = new Map(); @@ -143,8 +221,12 @@ module.exports = { const interfaceClassName = `${componentName}ViewManagerInterface`; const fileName = `${className}.java`; - const imports = getImports(component); + const imports = getDelegateImports(component); const propsString = generatePropCasesString(component, componentName); + const commandsString = generateCommandCasesString( + component, + componentName, + ); const extendString = getClassExtendString(component); const replacedTemplate = template @@ -155,9 +237,13 @@ module.exports = { .join('\n'), ) .replace(/::_CLASSNAME_::/g, className) - .replace(/::_INTERFACE_CLASSNAME_::/g, interfaceClassName) .replace('::_EXTEND_CLASSES_::', extendString) - .replace('::_PROP_CASES_::', propsString); + .replace('::_PROP_CASES_::', propsString) + .replace( + '::_METHODS_::', + generateMethods(propsString, commandsString), + ) + .replace(/::_INTERFACE_CLASSNAME_::/g, interfaceClassName); files.set(fileName, replacedTemplate); }); diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js index a13a091b3d6..e662477c08b 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js @@ -107,15 +107,14 @@ function getCommandArguments( command: CommandTypeShape, componentName: string, ): string { - const commandArgs = command.typeAnnotation.params - .map(param => { + return [ + 'T view', + ...command.typeAnnotation.params.map(param => { const commandArgJavaType = getCommandArgJavaType(param); return `${commandArgJavaType} ${param.name}`; - }) - .join(', '); - - return `T view, ${commandArgs}`; + }), + ].join(', '); } function generateCommandsString( @@ -124,11 +123,9 @@ function generateCommandsString( ) { return component.commands .map(command => { - const safeJavaName = toSafeJavaString(command.name); - const lowerJavaName = - safeJavaName[0].toLowerCase() + safeJavaName.slice(1); + const safeJavaName = toSafeJavaString(command.name, false); - return `void ${lowerJavaName}(${getCommandArguments( + return `void ${safeJavaName}(${getCommandArguments( command, componentName, )});`; diff --git a/packages/react-native-codegen/src/generators/components/JavaHelpers.js b/packages/react-native-codegen/src/generators/components/JavaHelpers.js index 7413fe4de15..61bcb365f86 100644 --- a/packages/react-native-codegen/src/generators/components/JavaHelpers.js +++ b/packages/react-native-codegen/src/generators/components/JavaHelpers.js @@ -16,11 +16,17 @@ function upperCaseFirst(inString: string): string { return inString[0].toUpperCase() + inString.slice(1); } -function toSafeJavaString(input: string): string { - return input - .split('-') - .map(upperCaseFirst) - .join(''); +function toSafeJavaString( + input: string, + shouldUpperCaseFirst?: boolean, +): string { + const parts = input.split('-'); + + if (shouldUpperCaseFirst === false) { + return parts.join(''); + } + + return parts.map(upperCaseFirst).join(''); } function getImports(component: ComponentShape): Set { diff --git a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js index 025825de9e7..e1d36d9ecba 100644 --- a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js @@ -921,6 +921,14 @@ const COMMANDS: SchemaType = { events: [], props: [], commands: [ + { + name: 'flashScrollIndicators', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + params: [], + }, + }, { name: 'hotspotUpdate', optional: false, diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap index f04f2cf7844..7298736e263 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap @@ -88,11 +88,24 @@ Map { package com.facebook.react.viewmanagers; import android.view.View; +import com.facebook.react.bridge.ReadableArray; public class CommandNativeComponentViewManagerDelegate { public void setProperty(CommandNativeComponentViewManagerInterface viewManager, T view, String propName, Object value) { // No props } + + public void receiveCommand(CommandNativeComponentViewManagerInterface viewManager, T view, String commandName, ReadableArray args) { + case \\"flashScrollIndicators\\": + viewManager.flashScrollIndicators(view); + break; + case \\"hotspotUpdate\\": + viewManager.hotspotUpdate(view, args.getInt(0), args.getInt(1)); + break; + case \\"scrollTo\\": + viewManager.scrollTo(view, args.getInt(0), args.getBoolean(1)); + break; + } } ", } @@ -104,6 +117,7 @@ Map { package com.facebook.react.viewmanagers; import android.view.View; +import com.facebook.react.bridge.ReadableArray; public class CommandNativeComponentViewManagerDelegate { public void setProperty(CommandNativeComponentViewManagerInterface viewManager, T view, String propName, Object value) { @@ -113,6 +127,12 @@ public class CommandNativeComponentViewManagerDelegate { break; } } + + public void receiveCommand(CommandNativeComponentViewManagerInterface viewManager, T view, String commandName, ReadableArray args) { + case \\"hotspotUpdate\\": + viewManager.hotspotUpdate(view, args.getInt(0), args.getInt(1)); + break; + } } ", } diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap index da606e801b0..c61813c9396 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap @@ -61,6 +61,7 @@ import android.view.View; public interface CommandNativeComponentViewManagerInterface { // No props + void flashScrollIndicators(T view); void hotspotUpdate(T view, int x, int y); void scrollTo(T view, int y, boolean animated); } diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap index 565e9750ce5..11d15d3c571 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -144,6 +144,14 @@ export const __INTERNAL_VIEW_CONFIG = CommandNativeComponentViewConfig; export default nativeComponentName; export const Commands = { + flashScrollIndicators(ref) { + UIManager.dispatchViewCommand( + findNodeHandle(ref), + UIManager.getViewManagerConfig(\\"CommandNativeComponent\\").Commands.flashScrollIndicators, + [] + ); + }, + hotspotUpdate(ref, x, y) { UIManager.dispatchViewCommand( findNodeHandle(ref),