Skip to content

Commit 65aee6c

Browse files
christophpurrermeta-codesync[bot]
authored andcommitted
Add centralized ReservedPrimitiveTypes registry and shared toSafeIdentifier helper (#56049)
Summary: Pull Request resolved: #56049 Reduce duplication and inconsistency across codegen generators by centralizing reserved primitive type mappings into a single `ReservedPrimitiveTypes.js` registry, making future type support and fixes a single-source change and lowering bug risk. Additionally, standardize identifier capitalization via a shared `toSafeIdentifier` helper in `Utils.js` to prevent divergent string handling across C++/Java helpers. Also removes dead TODO comments and obsolete commented-out code from `RNCodegen.js`, `GenerateModuleH.js`, and parser files. Changelog: [Internal] Reviewed By: alanleedev Differential Revision: D95711348 fbshipit-source-id: 3f541f91f8dcc21e8e8b75cf2f0e402807d18f8a
1 parent d8297f7 commit 65aee6c

9 files changed

Lines changed: 201 additions & 148 deletions

File tree

packages/react-native-codegen/src/generators/RNCodegen.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@
1010

1111
'use strict';
1212

13-
/*
14-
TODO:
15-
16-
- ViewConfigs should spread in View's valid attributes
17-
*/
18-
1913
import type {SchemaType} from '../CodegenSchema';
2014

2115
const schemaValidator = require('../SchemaValidator.js');
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict
8+
* @format
9+
*/
10+
11+
'use strict';
12+
13+
/**
14+
* Single source of truth for the 6 reserved primitive types used in
15+
* React Native component props. Each type maps to its per-language
16+
* representation (C++ type name, C++ includes, Java imports).
17+
*
18+
* Previously these mappings were scattered across CppHelpers.js,
19+
* ComponentsGeneratorUtils.js, and JavaHelpers.js.
20+
*/
21+
22+
export type ReservedPrimitiveName =
23+
| 'ColorPrimitive'
24+
| 'EdgeInsetsPrimitive'
25+
| 'ImageRequestPrimitive'
26+
| 'ImageSourcePrimitive'
27+
| 'PointPrimitive'
28+
| 'DimensionPrimitive';
29+
30+
type CppTypeInfo = {
31+
+typeName: string,
32+
+localIncludes: ReadonlyArray<string>,
33+
+conversionIncludes: ReadonlyArray<string>,
34+
};
35+
36+
type JavaImportInfo = {
37+
+interfaceImports: ReadonlyArray<string>,
38+
+delegateImports: ReadonlyArray<string>,
39+
};
40+
41+
type ReservedTypeMapping = {
42+
+cpp: CppTypeInfo,
43+
+java: JavaImportInfo,
44+
};
45+
46+
const RESERVED_TYPES: {+[ReservedPrimitiveName]: ReservedTypeMapping} = {
47+
ColorPrimitive: {
48+
cpp: {
49+
typeName: 'SharedColor',
50+
localIncludes: ['#include <react/renderer/graphics/Color.h>'],
51+
conversionIncludes: [],
52+
},
53+
java: {
54+
interfaceImports: [],
55+
delegateImports: ['import com.facebook.react.bridge.ColorPropConverter;'],
56+
},
57+
},
58+
ImageSourcePrimitive: {
59+
cpp: {
60+
typeName: 'ImageSource',
61+
localIncludes: ['#include <react/renderer/imagemanager/primitives.h>'],
62+
conversionIncludes: [
63+
'#include <react/renderer/components/image/conversions.h>',
64+
],
65+
},
66+
java: {
67+
interfaceImports: ['import com.facebook.react.bridge.ReadableMap;'],
68+
delegateImports: ['import com.facebook.react.bridge.ReadableMap;'],
69+
},
70+
},
71+
ImageRequestPrimitive: {
72+
cpp: {
73+
typeName: 'ImageRequest',
74+
localIncludes: ['#include <react/renderer/imagemanager/ImageRequest.h>'],
75+
conversionIncludes: [],
76+
},
77+
java: {
78+
// ImageRequestPrimitive is not used in Java component props
79+
interfaceImports: [],
80+
delegateImports: [],
81+
},
82+
},
83+
PointPrimitive: {
84+
cpp: {
85+
typeName: 'Point',
86+
localIncludes: ['#include <react/renderer/graphics/Point.h>'],
87+
conversionIncludes: [],
88+
},
89+
java: {
90+
interfaceImports: ['import com.facebook.react.bridge.ReadableMap;'],
91+
delegateImports: ['import com.facebook.react.bridge.ReadableMap;'],
92+
},
93+
},
94+
EdgeInsetsPrimitive: {
95+
cpp: {
96+
typeName: 'EdgeInsets',
97+
localIncludes: ['#include <react/renderer/graphics/RectangleEdges.h>'],
98+
conversionIncludes: [],
99+
},
100+
java: {
101+
interfaceImports: ['import com.facebook.react.bridge.ReadableMap;'],
102+
delegateImports: ['import com.facebook.react.bridge.ReadableMap;'],
103+
},
104+
},
105+
DimensionPrimitive: {
106+
cpp: {
107+
typeName: 'YGValue',
108+
localIncludes: [
109+
'#include <yoga/Yoga.h>',
110+
'#include <react/renderer/core/graphicsConversions.h>',
111+
],
112+
conversionIncludes: [
113+
'#include <react/renderer/components/view/conversions.h>',
114+
],
115+
},
116+
java: {
117+
interfaceImports: ['import com.facebook.yoga.YogaValue;'],
118+
delegateImports: [
119+
'import com.facebook.react.bridge.DimensionPropConverter;',
120+
],
121+
},
122+
},
123+
};
124+
125+
function getCppTypeForReservedPrimitive(name: ReservedPrimitiveName): string {
126+
return RESERVED_TYPES[name].cpp.typeName;
127+
}
128+
129+
function getCppLocalIncludesForReservedPrimitive(
130+
name: ReservedPrimitiveName,
131+
): ReadonlyArray<string> {
132+
return RESERVED_TYPES[name].cpp.localIncludes;
133+
}
134+
135+
function getCppConversionIncludesForReservedPrimitive(
136+
name: ReservedPrimitiveName,
137+
): ReadonlyArray<string> {
138+
return RESERVED_TYPES[name].cpp.conversionIncludes;
139+
}
140+
141+
function getJavaImportsForReservedPrimitive(
142+
name: ReservedPrimitiveName,
143+
type: 'interface' | 'delegate',
144+
): ReadonlyArray<string> {
145+
const info = RESERVED_TYPES[name].java;
146+
return type === 'interface' ? info.interfaceImports : info.delegateImports;
147+
}
148+
149+
module.exports = {
150+
RESERVED_TYPES,
151+
getCppTypeForReservedPrimitive,
152+
getCppLocalIncludesForReservedPrimitive,
153+
getCppConversionIncludesForReservedPrimitive,
154+
getJavaImportsForReservedPrimitive,
155+
};

packages/react-native-codegen/src/generators/Utils.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,19 @@ function toPascalCase(inString: string): string {
3434
return inString;
3535
}
3636

37-
return inString[0].toUpperCase() + inString.slice(1);
37+
return capitalize(inString);
38+
}
39+
40+
function toSafeIdentifier(input: string, shouldCapitalize: boolean): string {
41+
const parts = input.split('-');
42+
if (!shouldCapitalize) {
43+
return parts.join('');
44+
}
45+
return parts.map(toPascalCase).join('');
3846
}
3947

4048
function toSafeCppString(input: string): string {
41-
return input.split('-').map(toPascalCase).join('');
49+
return toSafeIdentifier(input, true);
4250
}
4351

4452
function getEnumName(moduleName: string, origEnumName: string): string {
@@ -105,6 +113,7 @@ module.exports = {
105113
indent,
106114
parseValidUnionType,
107115
toPascalCase,
116+
toSafeIdentifier,
108117
toSafeCppString,
109118
getEnumName,
110119
HeterogeneousUnionError,

packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js

Lines changed: 21 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import type {
2121
StringTypeAnnotation,
2222
} from '../../CodegenSchema';
2323

24+
const {
25+
getCppLocalIncludesForReservedPrimitive,
26+
getCppTypeForReservedPrimitive,
27+
} = require('../ReservedPrimitiveTypes');
2428
const {getEnumName} = require('../Utils');
2529
const {
2630
generateStructName,
@@ -66,23 +70,7 @@ function getNativeTypeFromAnnotation(
6670
case 'FloatTypeAnnotation':
6771
return getCppTypeForAnnotation(typeAnnotation.type);
6872
case 'ReservedPropTypeAnnotation':
69-
switch (typeAnnotation.name) {
70-
case 'ColorPrimitive':
71-
return 'SharedColor';
72-
case 'ImageSourcePrimitive':
73-
return 'ImageSource';
74-
case 'ImageRequestPrimitive':
75-
return 'ImageRequest';
76-
case 'PointPrimitive':
77-
return 'Point';
78-
case 'EdgeInsetsPrimitive':
79-
return 'EdgeInsets';
80-
case 'DimensionPrimitive':
81-
return 'YGValue';
82-
default:
83-
(typeAnnotation.name: empty);
84-
throw new Error('Received unknown ReservedPropTypeAnnotation');
85-
}
73+
return getCppTypeForReservedPrimitive(typeAnnotation.name);
8674
case 'ArrayTypeAnnotation': {
8775
const arrayType = typeAnnotation.elementType.type;
8876
if (arrayType === 'ArrayTypeAnnotation') {
@@ -175,43 +163,25 @@ function convertVariableToPointer(
175163
return value;
176164
}
177165

178-
const convertCtorParamToAddressType = (type: string): string => {
179-
const typesToConvert: Set<string> = new Set();
180-
typesToConvert.add('ImageSource');
166+
// Configuration for C++ type conversions of reserved types.
167+
// Centralizes the knowledge of which types need special pointer/address handling.
168+
const CTOR_PARAM_ADDRESS_TYPES: Set<string> = new Set(['ImageSource']);
169+
const SHARED_POINTER_TYPES: Set<string> = new Set(['ImageRequest']);
181170

182-
return convertTypesToConstAddressIfNeeded(type, typesToConvert);
183-
};
171+
const convertCtorParamToAddressType = (type: string): string =>
172+
convertTypesToConstAddressIfNeeded(type, CTOR_PARAM_ADDRESS_TYPES);
184173

185-
const convertCtorInitToSharedPointers = (
186-
type: string,
187-
value: string,
188-
): string => {
189-
const typesToConvert: Set<string> = new Set();
190-
typesToConvert.add('ImageRequest');
174+
const convertCtorInitToSharedPointers = (type: string, value: string): string =>
175+
convertValueToSharedPointerWithMove(type, value, SHARED_POINTER_TYPES);
191176

192-
return convertValueToSharedPointerWithMove(type, value, typesToConvert);
193-
};
177+
const convertGettersReturnTypeToAddressType = (type: string): string =>
178+
convertTypesToConstAddressIfNeeded(type, SHARED_POINTER_TYPES);
194179

195-
const convertGettersReturnTypeToAddressType = (type: string): string => {
196-
const typesToConvert: Set<string> = new Set();
197-
typesToConvert.add('ImageRequest');
180+
const convertVarTypeToSharedPointer = (type: string): string =>
181+
convertVariableToSharedPointer(type, SHARED_POINTER_TYPES);
198182

199-
return convertTypesToConstAddressIfNeeded(type, typesToConvert);
200-
};
201-
202-
const convertVarTypeToSharedPointer = (type: string): string => {
203-
const typesToConvert: Set<string> = new Set();
204-
typesToConvert.add('ImageRequest');
205-
206-
return convertVariableToSharedPointer(type, typesToConvert);
207-
};
208-
209-
const convertVarValueToPointer = (type: string, value: string): string => {
210-
const typesToConvert: Set<string> = new Set();
211-
typesToConvert.add('ImageRequest');
212-
213-
return convertVariableToPointer(type, value, typesToConvert);
214-
};
183+
const convertVarValueToPointer = (type: string, value: string): string =>
184+
convertVariableToPointer(type, value, SHARED_POINTER_TYPES);
215185

216186
function getLocalImports(
217187
properties: ReadonlyArray<NamedShape<PropTypeAnnotation>>,
@@ -227,29 +197,8 @@ function getLocalImports(
227197
| 'ImageRequestPrimitive'
228198
| 'DimensionPrimitive',
229199
) {
230-
switch (name) {
231-
case 'ColorPrimitive':
232-
imports.add('#include <react/renderer/graphics/Color.h>');
233-
return;
234-
case 'ImageSourcePrimitive':
235-
imports.add('#include <react/renderer/imagemanager/primitives.h>');
236-
return;
237-
case 'ImageRequestPrimitive':
238-
imports.add('#include <react/renderer/imagemanager/ImageRequest.h>');
239-
return;
240-
case 'PointPrimitive':
241-
imports.add('#include <react/renderer/graphics/Point.h>');
242-
return;
243-
case 'EdgeInsetsPrimitive':
244-
imports.add('#include <react/renderer/graphics/RectangleEdges.h>');
245-
return;
246-
case 'DimensionPrimitive':
247-
imports.add('#include <yoga/Yoga.h>');
248-
imports.add('#include <react/renderer/core/graphicsConversions.h>');
249-
return;
250-
default:
251-
(name: empty);
252-
throw new Error(`Invalid ReservedPropTypeAnnotation name, got ${name}`);
200+
for (const include of getCppLocalIncludesForReservedPrimitive(name)) {
201+
imports.add(include);
253202
}
254203
}
255204

packages/react-native-codegen/src/generators/components/CppHelpers.js

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import type {
1515
PropTypeAnnotation,
1616
} from '../../CodegenSchema';
1717

18+
const {
19+
getCppConversionIncludesForReservedPrimitive,
20+
} = require('../ReservedPrimitiveTypes');
1821
const {getEnumName, parseValidUnionType, toSafeCppString} = require('../Utils');
1922

2023
function toIntEnumValueName(propName: string, value: number): string {
@@ -134,24 +137,8 @@ function getImports(
134137
| 'PointPrimitive'
135138
| 'DimensionPrimitive',
136139
) {
137-
switch (name) {
138-
case 'ColorPrimitive':
139-
return;
140-
case 'PointPrimitive':
141-
return;
142-
case 'EdgeInsetsPrimitive':
143-
return;
144-
case 'ImageRequestPrimitive':
145-
return;
146-
case 'ImageSourcePrimitive':
147-
imports.add('#include <react/renderer/components/image/conversions.h>');
148-
return;
149-
case 'DimensionPrimitive':
150-
imports.add('#include <react/renderer/components/view/conversions.h>');
151-
return;
152-
default:
153-
(name: empty);
154-
throw new Error(`Invalid name, got ${name}`);
140+
for (const include of getCppConversionIncludesForReservedPrimitive(name)) {
141+
imports.add(include);
155142
}
156143
}
157144

0 commit comments

Comments
 (0)