diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js index 6ab7dc8980e..5350dae282d 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js @@ -11,6 +11,7 @@ 'use strict'; import type { + CommandTypeShape, ComponentShape, PropTypeShape, SchemaType, @@ -26,7 +27,7 @@ package com.facebook.react.viewmanagers; ::_IMPORTS_:: public interface ::_CLASSNAME_:: { - ::_PROP_SETTERS_:: + ::_METHODS_:: } `; @@ -70,7 +71,7 @@ function getJavaValueForProp( function generatePropsString(component: ComponentShape, componentName: string) { if (component.props.length === 0) { - return ' // No props'; + return '// No props'; } return component.props @@ -82,6 +83,51 @@ function generatePropsString(component: ComponentShape, componentName: string) { .join('\n' + ' '); } +function getCommandArgJavaType(param) { + switch (param.typeAnnotation.type) { + case 'BooleanTypeAnnotation': + return 'boolean'; + case 'Int32TypeAnnotation': + return 'int'; + default: + (param.typeAnnotation.type: empty); + throw new Error('Receieved invalid typeAnnotation'); + } +} + +function getCommandArguments( + command: CommandTypeShape, + componentName: string, +): string { + const commandArgs = command.typeAnnotation.params + .map(param => { + const commandArgJavaType = getCommandArgJavaType(param); + + return `${commandArgJavaType} ${param.name}`; + }) + .join(', '); + + return `T view, ${commandArgs}`; +} + +function generateCommandsString( + component: ComponentShape, + componentName: string, +) { + return component.commands + .map(command => { + const safeJavaName = toSafeJavaString(command.name); + const lowerJavaName = + safeJavaName[0].toLowerCase() + safeJavaName.slice(1); + + return `void ${lowerJavaName}(${getCommandArguments( + command, + componentName, + )});`; + }) + .join('\n' + ' '); +} + function getClassExtendString(component): string { const extendString = component.extendsProps .map(extendProps => { @@ -121,6 +167,7 @@ module.exports = { const imports = getImports(component); const propsString = generatePropsString(component, componentName); + const commandsString = generateCommandsString(component, componentName); const extendString = getClassExtendString(component); const replacedTemplate = template @@ -132,7 +179,11 @@ module.exports = { ) .replace(/::_CLASSNAME_::/g, className) .replace('::_EXTEND_CLASSES_::', extendString) - .replace('::_PROP_SETTERS_::', propsString); + .replace( + '::_METHODS_::', + [propsString, commandsString].join('\n' + ' ').trimRight(), + ) + .replace('::_COMMAND_HANDLERS_::', commandsString); files.set(fileName, replacedTemplate); }); 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 38fa9abddbc..8b3661fe7f5 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 @@ -970,6 +970,57 @@ const COMMANDS: SchemaType = { }, }; +const COMMANDS_AND_PROPS: SchemaType = { + modules: { + Switch: { + components: { + CommandNativeComponent: { + extendsProps: [ + { + type: 'ReactNativeBuiltInType', + knownTypeName: 'ReactNativeCoreViewProps', + }, + ], + events: [], + props: [ + { + name: 'accessibilityHint', + optional: true, + typeAnnotation: { + type: 'StringTypeAnnotation', + default: '', + }, + }, + ], + commands: [ + { + name: 'hotspotUpdate', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + params: [ + { + name: 'x', + typeAnnotation: { + type: 'Int32TypeAnnotation', + }, + }, + { + name: 'y', + typeAnnotation: { + type: 'Int32TypeAnnotation', + }, + }, + ], + }, + }, + ], + }, + }, + }, + }, +}; + module.exports = { NO_PROPS_NO_EVENTS, INTERFACE_ONLY, @@ -989,4 +1040,5 @@ module.exports = { TWO_COMPONENTS_SAME_FILE, TWO_COMPONENTS_DIFFERENT_FILES, COMMANDS, + COMMANDS_AND_PROPS, }; diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap index c6af7e4ef34..7b21c6b3a75 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap @@ -86,6 +86,29 @@ namespace react { +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateEventEmitterCpp can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "EventEmitters.cpp" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace facebook { +namespace react { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap index 27c262e892d..f8dacb3b105 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap @@ -90,6 +90,30 @@ namespace react { +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateEventEmitterH can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "EventEmitters.h" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#pragma once + +#include + +namespace facebook { +namespace react { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap index 23bf7c08511..8e6663af96f 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap @@ -124,6 +124,35 @@ CommandNativeComponentProps::CommandNativeComponentProps( } `; +exports[`GeneratePropsCpp can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "Props.cpp" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +namespace facebook { +namespace react { + +CommandNativeComponentProps::CommandNativeComponentProps( + const CommandNativeComponentProps &sourceProps, + const RawProps &rawProps): ViewProps(sourceProps, rawProps), + + accessibilityHint(convertRawProp(rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, accessibilityHint)) + {} + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GeneratePropsCpp can generate fixture ENUM_PROP 1`] = ` Map { "Props.cpp" => " diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap index ed3e7a50c47..45c1d0ebdc0 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsH-test.js.snap @@ -197,6 +197,38 @@ class CommandNativeComponentProps final : public ViewProps { } `; +exports[`GeneratePropsH can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "Props.h" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#pragma once + +#include + +namespace facebook { +namespace react { + +class CommandNativeComponentProps final : public ViewProps { + public: + CommandNativeComponentProps() = default; + CommandNativeComponentProps(const CommandNativeComponentProps &sourceProps, const RawProps &rawProps); + +#pragma mark - Props + + const std::string accessibilityHint{\\"\\"}; +}; + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GeneratePropsH can generate fixture ENUM_PROP 1`] = ` Map { "Props.h" => " 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 cbb91923e39..3fefa8a3eca 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 @@ -100,6 +100,26 @@ public class CommandNativeComponentDelegate { } `; +exports[`GeneratePropsJavaDelegate can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "CommandNativeComponentDelegate.java" => " +package com.facebook.react.viewmanagers; + +import android.view.View; + +public class CommandNativeComponentDelegate { + public void setProperty(CommandNativeComponentInterface viewManager, T view, String propName, Object value) { + switch (propName) { + case \\"accessibilityHint\\": + viewManager.setAccessibilityHint(view, (String) value); + break; + } + } +} +", +} +`; + exports[`GeneratePropsJavaDelegate can generate fixture ENUM_PROP 1`] = ` Map { "EnumPropsNativeComponentDelegate.java" => " 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 f704042e71a..1ce8aceb8be 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 @@ -58,7 +58,24 @@ package com.facebook.react.viewmanagers; import android.view.View; public interface CommandNativeComponentInterface { - // No props + // No props + void hotspotUpdate(T view, int x, int y); + void scrollTo(T view, int y, boolean animated); +} +", +} +`; + +exports[`GeneratePropsJavaInterface can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "CommandNativeComponentInterface.java" => " +package com.facebook.react.viewmanagers; + +import android.view.View; + +public interface CommandNativeComponentInterface { + void setAccessibilityHint(T view, String value); + void hotspotUpdate(T view, int x, int y); } ", } @@ -114,7 +131,7 @@ package com.facebook.react.viewmanagers; import android.view.View; public interface InterfaceOnlyComponentInterface { - // No props + // No props } ", } @@ -210,7 +227,7 @@ package com.facebook.react.viewmanagers; import android.view.View; public interface NoPropsNoEventsComponentInterface { - // No props + // No props } ", } diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap index 4ca1e384aaa..a62e4d17fdb 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap @@ -92,6 +92,29 @@ extern const char CommandNativeComponentComponentName[] = \\"CommandNativeCompon } `; +exports[`GenerateShadowNodeCpp can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "ShadowNodes.cpp" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace facebook { +namespace react { + +extern const char CommandNativeComponentComponentName[] = \\"CommandNativeComponent\\"; + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GenerateShadowNodeCpp can generate fixture ENUM_PROP 1`] = ` Map { "ShadowNodes.cpp" => " diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap index 40ba9a8a92c..7d3962d5034 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap @@ -132,6 +132,39 @@ using CommandNativeComponentShadowNode = ConcreteViewShadowNode< } `; +exports[`GenerateShadowNodeH can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "ShadowNodes.h" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +extern const char CommandNativeComponentComponentName[]; + +/* + * \`ShadowNode\` for component. + */ +using CommandNativeComponentShadowNode = ConcreteViewShadowNode< + CommandNativeComponentComponentName, + CommandNativeComponentProps>; + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GenerateShadowNodeH can generate fixture ENUM_PROP 1`] = ` Map { "ShadowNodes.h" => " diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap index 413b2b5a85a..e44041d6138 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateTests-test.js.snap @@ -131,6 +131,43 @@ TEST(CommandNativeComponentProps_DoesNotDie, etc) { } `; +exports[`GenerateTests can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "Tests.cpp" => "/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include +#include +#include + +using namespace facebook::react; + +TEST(CommandNativeComponentProps_DoesNotDie, etc) { + auto propParser = RawPropsParser(); + propParser.prepare(); + auto const &sourceProps = CommandNativeComponentProps(); + auto const &rawProps = RawProps(folly::dynamic::object(\\"xx_invalid_xx\\", \\"xx_invalid_xx\\")); + rawProps.parse(propParser); + CommandNativeComponentProps(sourceProps, rawProps); +} + +TEST(CommandNativeComponentProps_accessibilityHint, etc) { + auto propParser = RawPropsParser(); + propParser.prepare(); + auto const &sourceProps = CommandNativeComponentProps(); + auto const &rawProps = RawProps(folly::dynamic::object(\\"accessibilityHint\\", \\"foo\\")); + rawProps.parse(propParser); + CommandNativeComponentProps(sourceProps, rawProps); +}", +} +`; + exports[`GenerateTests can generate fixture ENUM_PROP 1`] = ` Map { "Tests.cpp" => "/** 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 654784c2a1a..565e9750ce5 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 @@ -164,6 +164,53 @@ export const Commands = { } `; +exports[`GenerateViewConfigJs can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "COMMANDS_AND_PROPSNativeViewConfig.js" => " +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +'use strict'; + +const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const {UIManager} = require(\\"react-native\\") +const {findNodeHandle} = require(\\"react-native\\") + +const CommandNativeComponentViewConfig = { + uiViewClassName: 'CommandNativeComponent', + + validAttributes: { + accessibilityHint: true, + }, +}; + +let nativeComponentName = 'CommandNativeComponent'; + +registerGeneratedViewConfig(nativeComponentName, CommandNativeComponentViewConfig); + +export const __INTERNAL_VIEW_CONFIG = CommandNativeComponentViewConfig; + +export default nativeComponentName; + +export const Commands = { + hotspotUpdate(ref, x, y) { + UIManager.dispatchViewCommand( + findNodeHandle(ref), + UIManager.getViewManagerConfig(\\"CommandNativeComponent\\").Commands.hotspotUpdate, + [x, y] + ); + } +}; +", +} +`; + exports[`GenerateViewConfigJs can generate fixture ENUM_PROP 1`] = ` Map { "ENUM_PROPNativeViewConfig.js" => "