diff --git a/packages/react-native-codegen/BUCK b/packages/react-native-codegen/BUCK index a1d97d26b0b..38e5f4c9c0d 100644 --- a/packages/react-native-codegen/BUCK +++ b/packages/react-native-codegen/BUCK @@ -43,6 +43,10 @@ fb_native.sh_binary( visibility = ["PUBLIC"], ) +rn_codegen_test( + fixture_name = "INTERFACE_ONLY", +) + rn_codegen_test( fixture_name = "BOOLEAN_PROP", ) @@ -115,6 +119,7 @@ fb_xplat_cxx_binary( ":generated_components-FLOAT_PROPS", ":generated_components-IMAGE_PROP", ":generated_components-INTEGER_PROPS", + ":generated_components-INTERFACE_ONLY", ":generated_components-MULTI_NATIVE_PROP", ":generated_components-STRING_PROP", ":generated_components-TWO_COMPONENTS_DIFFERENT_FILES", @@ -149,6 +154,7 @@ rn_xplat_cxx_library( ":generated_components-FLOAT_PROPS", ":generated_components-IMAGE_PROP", ":generated_components-INTEGER_PROPS", + ":generated_components-INTERFACE_ONLY", ":generated_components-MULTI_NATIVE_PROP", ":generated_components-STRING_PROP", ":generated_components-TWO_COMPONENTS_DIFFERENT_FILES", diff --git a/packages/react-native-codegen/buck_tests/emptyFile.cpp b/packages/react-native-codegen/buck_tests/emptyFile.cpp index bf041a6b52f..d08daa8d046 100644 --- a/packages/react-native-codegen/buck_tests/emptyFile.cpp +++ b/packages/react-native-codegen/buck_tests/emptyFile.cpp @@ -1,3 +1,4 @@ +#import #import #import #import diff --git a/packages/react-native-codegen/src/CodegenSchema.js b/packages/react-native-codegen/src/CodegenSchema.js index 4af0aca60bb..ee2d763f29e 100644 --- a/packages/react-native-codegen/src/CodegenSchema.js +++ b/packages/react-native-codegen/src/CodegenSchema.js @@ -87,6 +87,7 @@ export type EventTypeShape = $ReadOnly<{| |}>; export type ComponentShape = $ReadOnly<{| + interfaceOnly?: boolean, extendsProps: $ReadOnlyArray<{| type: 'ReactNativeBuiltInType', knownTypeName: 'ReactNativeCoreViewProps', diff --git a/packages/react-native-codegen/src/generators/GenerateComponentDescriptorH.js b/packages/react-native-codegen/src/generators/GenerateComponentDescriptorH.js index c4e1e5a316b..24f85fee9a1 100644 --- a/packages/react-native-codegen/src/generators/GenerateComponentDescriptorH.js +++ b/packages/react-native-codegen/src/generators/GenerateComponentDescriptorH.js @@ -55,6 +55,9 @@ module.exports = { return Object.keys(components) .map(componentName => { + if (components[componentName].interfaceOnly === true) { + return; + } return componentTemplate.replace(/::_CLASSNAME_::/g, componentName); }) .join('\n'); diff --git a/packages/react-native-codegen/src/generators/GenerateShadowNodeCpp.js b/packages/react-native-codegen/src/generators/GenerateShadowNodeCpp.js index 6b3467ee1ab..0210aaa2239 100644 --- a/packages/react-native-codegen/src/generators/GenerateShadowNodeCpp.js +++ b/packages/react-native-codegen/src/generators/GenerateShadowNodeCpp.js @@ -52,6 +52,9 @@ module.exports = { return Object.keys(components) .map(componentName => { + if (components[componentName].interfaceOnly === true) { + return; + } const replacedTemplate = componentTemplate.replace( /::_CLASSNAME_::/g, componentName, diff --git a/packages/react-native-codegen/src/generators/GenerateShadowNodeH.js b/packages/react-native-codegen/src/generators/GenerateShadowNodeH.js index f365e490d14..59501c99c85 100644 --- a/packages/react-native-codegen/src/generators/GenerateShadowNodeH.js +++ b/packages/react-native-codegen/src/generators/GenerateShadowNodeH.js @@ -65,6 +65,10 @@ module.exports = { return Object.keys(components) .map(componentName => { const component = components[componentName]; + if (component.interfaceOnly === true) { + return; + } + const hasEvents = component.events.length > 0; if (hasEvents) { diff --git a/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js index 582eb2be3b1..bfbfa7ab232 100644 --- a/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js @@ -12,6 +12,54 @@ import type {SchemaType} from '../../CodegenSchema.js'; +const INTERFACE_ONLY: SchemaType = { + modules: { + Switch: { + components: { + InterfaceOnlyComponent: { + interfaceOnly: true, + extendsProps: [ + { + type: 'ReactNativeBuiltInType', + knownTypeName: 'ReactNativeCoreViewProps', + }, + ], + events: [ + { + name: 'onChange', + optional: true, + bubblingType: 'bubble', + typeAnnotation: { + type: 'EventTypeAnnotation', + argument: { + type: 'ObjectTypeAnnotation', + properties: [ + { + type: 'BooleanTypeAnnotation', + name: 'value', + optional: false, + }, + ], + }, + }, + }, + ], + props: [ + { + name: 'accessibilityHint', + optional: true, + typeAnnotation: { + type: 'StringTypeAnnotation', + default: '', + }, + }, + ], + }, + }, + }, + }, +}; + const BOOLEAN_PROP: SchemaType = { modules: { Switch: { @@ -580,6 +628,7 @@ const TWO_COMPONENTS_DIFFERENT_FILES: SchemaType = { }; module.exports = { + INTERFACE_ONLY, BOOLEAN_PROP, STRING_PROP, INTEGER_PROPS, diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap index bb68b3796d1..b55e9f5bac4 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterCpp-test.js.snap @@ -212,6 +212,35 @@ namespace react { +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateEventEmitterCpp can generate fixture INTERFACE_ONLY 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 { + +void InterfaceOnlyComponentEventEmitter::onChange(InterfaceOnlyComponentOnChangeStruct event) const { + dispatchEvent(\\"change\\", [event=std::move(event)](jsi::Runtime &runtime) { + auto payload = jsi::Object(runtime); + payload.setProperty(runtime, \\"value\\", event.value); + return payload; + }); +} + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap index f6634f35861..33bf6f768ff 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateEventEmitterH-test.js.snap @@ -223,6 +223,39 @@ namespace react { +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateEventEmitterH can generate fixture INTERFACE_ONLY 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 { + +struct InterfaceOnlyComponentOnChangeStruct { + bool value; +}; + +class InterfaceOnlyComponentEventEmitter : public ViewEventEmitter { + public: + using ViewEventEmitter::ViewEventEmitter; + + void onChange(InterfaceOnlyComponentOnChangeStruct value) const; +}; + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap index 69ea1adbebf..dfd4d724ba6 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsCpp-test.js.snap @@ -239,6 +239,35 @@ progress3(convertRawProp(rawProps, \\"progress3\\", sourceProps.progress3, progr } `; +exports[`GeneratePropsCpp can generate fixture INTERFACE_ONLY 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 { + +InterfaceOnlyComponentProps::InterfaceOnlyComponentProps( + const InterfaceOnlyComponentProps &sourceProps, + const RawProps &rawProps): ViewProps(sourceProps, rawProps), + + accessibilityHint(convertRawProp(rawProps, \\"accessibilityHint\\", sourceProps.accessibilityHint, accessibilityHint)) + {} + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GeneratePropsCpp can generate fixture MULTI_NATIVE_PROP 1`] = ` Map { "Props.cpp" => " diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap index d155bcabb50..c5f86c2109f 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GeneratePropsH-test.js.snap @@ -274,6 +274,37 @@ const int progress3{10}; } `; +exports[`GeneratePropsH can generate fixture INTERFACE_ONLY 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. + */ + +#include + +namespace facebook { +namespace react { + +class InterfaceOnlyComponentProps final : public ViewProps { + public: + InterfaceOnlyComponentProps() = default; + InterfaceOnlyComponentProps(const InterfaceOnlyComponentProps &sourceProps, const RawProps &rawProps); + +#pragma mark - Props + + const std::string accessibilityHint{\\"\\"}; +}; + +} // namespace react +} // namespace facebook +", +} +`; + exports[`GeneratePropsH can generate fixture MULTI_NATIVE_PROP 1`] = ` Map { "Props.h" => " diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap index 6cd3422d2f7..64a9a6f5f18 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeCpp-test.js.snap @@ -178,6 +178,29 @@ namespace react { extern const char IntegerPropNativeComponentComponentName[] = \\"IntegerPropNativeComponent\\"; +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateShadowNodeCpp can generate fixture INTERFACE_ONLY 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 { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap index 0fc22b2fe58..9b40789cc62 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateShadowNodeH-test.js.snap @@ -262,6 +262,32 @@ using IntegerPropNativeComponentShadowNode = ConcreteViewShadowNode< IntegerPropNativeComponentComponentName, IntegerPropNativeComponentProps>; +} // namespace react +} // namespace facebook +", +} +`; + +exports[`GenerateShadowNodeH can generate fixture INTERFACE_ONLY 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 { + + + } // namespace react } // namespace facebook ", diff --git a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap index e5effa2ce27..0358579cda5 100644 --- a/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/src/generators/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -310,6 +310,50 @@ ReactNativeViewConfigRegistry.register( } `; +exports[`GenerateViewConfigJs can generate fixture INTERFACE_ONLY 1`] = ` +Map { + "ViewConfigs.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. + * + * @format + * @flow + */ + +'use strict'; + +const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); +const ReactNativeViewConfigRegistry = require('ReactNativeViewConfigRegistry'); + +const InterfaceOnlyComponentViewConfig = { + uiViewClassName: 'InterfaceOnlyComponent', + + bubblingEventTypes: { + onChange: { + phasedRegistrationNames: { + captured: 'onChangeCapture', + bubbled: 'onChange' + } + } + }, + + validAttributes: { + accessibilityHint: true, + style: ReactNativeStyleAttributes + } +}; + +ReactNativeViewConfigRegistry.register( + 'InterfaceOnlyComponent', + () => InterfaceOnlyComponentViewConfig, +); +", +} +`; + exports[`GenerateViewConfigJs can generate fixture MULTI_NATIVE_PROP 1`] = ` Map { "ViewConfigs.js" => "